@workflow/web-shared 5.0.0-beta.6 → 5.0.0-beta.8

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 (200) hide show
  1. package/dist/components/error-boundary.js +1 -1
  2. package/dist/components/event-list-view.d.ts +12 -0
  3. package/dist/components/event-list-view.d.ts.map +1 -1
  4. package/dist/components/event-list-view.js +26 -13
  5. package/dist/components/hook-actions.js +1 -1
  6. package/dist/components/index.js +1 -1
  7. package/dist/components/new-trace-viewer/components/copy-button.js +2 -2
  8. package/dist/components/new-trace-viewer/components/event-list.js +3 -3
  9. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +1 -1
  10. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +1 -1
  11. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +1 -1
  12. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +1 -1
  13. package/dist/components/new-trace-viewer/components/split-pane.js +1 -1
  14. package/dist/components/new-trace-viewer/components/timeline.d.ts +1 -1
  15. package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -1
  16. package/dist/components/new-trace-viewer/components/timeline.js +187 -103
  17. package/dist/components/new-trace-viewer/context.js +1 -1
  18. package/dist/components/new-trace-viewer/detail-panel.js +2 -2
  19. package/dist/components/new-trace-viewer/icons.js +1 -1
  20. package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -1
  21. package/dist/components/new-trace-viewer/trace-viewer.js +53 -26
  22. package/dist/components/new-trace-viewer/types.js +1 -1
  23. package/dist/components/new-trace-viewer/util/constants.js +1 -1
  24. package/dist/components/new-trace-viewer/utils.d.ts +8 -4
  25. package/dist/components/new-trace-viewer/utils.d.ts.map +1 -1
  26. package/dist/components/new-trace-viewer/utils.js +31 -6
  27. package/dist/components/run-trace-view.js +1 -1
  28. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  29. package/dist/components/sidebar/attribute-panel.js +99 -73
  30. package/dist/components/sidebar/conversation-view.js +1 -1
  31. package/dist/components/sidebar/copyable-data-block.d.ts +1 -0
  32. package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
  33. package/dist/components/sidebar/copyable-data-block.js +16 -15
  34. package/dist/components/sidebar/detail-card.d.ts +5 -6
  35. package/dist/components/sidebar/detail-card.d.ts.map +1 -1
  36. package/dist/components/sidebar/detail-card.js +32 -16
  37. package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
  38. package/dist/components/sidebar/entity-detail-panel.js +6 -3
  39. package/dist/components/sidebar/events-list.d.ts.map +1 -1
  40. package/dist/components/sidebar/events-list.js +21 -15
  41. package/dist/components/sidebar/resolve-hook-modal.js +1 -1
  42. package/dist/components/sidebar/sidebar-data-context.js +1 -1
  43. package/dist/components/stream-viewer.js +1 -1
  44. package/dist/components/trace-viewer/components/map.js +1 -1
  45. package/dist/components/trace-viewer/components/markers.js +1 -1
  46. package/dist/components/trace-viewer/components/node.js +1 -1
  47. package/dist/components/trace-viewer/components/search-input.js +1 -1
  48. package/dist/components/trace-viewer/components/search.js +1 -1
  49. package/dist/components/trace-viewer/components/span-content.js +1 -1
  50. package/dist/components/trace-viewer/components/span-detail-panel.js +1 -1
  51. package/dist/components/trace-viewer/components/span-segments.js +1 -1
  52. package/dist/components/trace-viewer/components/span-strategies.js +1 -1
  53. package/dist/components/trace-viewer/components/ui.js +1 -1
  54. package/dist/components/trace-viewer/components/zoom-button.js +1 -1
  55. package/dist/components/trace-viewer/components/zoom-icons.js +1 -1
  56. package/dist/components/trace-viewer/context.js +1 -1
  57. package/dist/components/trace-viewer/index.js +1 -1
  58. package/dist/components/trace-viewer/trace-viewer.js +1 -1
  59. package/dist/components/trace-viewer/types.js +1 -1
  60. package/dist/components/trace-viewer/util/constants.js +1 -1
  61. package/dist/components/trace-viewer/util/scrollbar-width.js +1 -1
  62. package/dist/components/trace-viewer/util/timing.js +1 -1
  63. package/dist/components/trace-viewer/util/tree.js +1 -1
  64. package/dist/components/trace-viewer/util/use-immediate-style.js +1 -1
  65. package/dist/components/trace-viewer/util/use-streaming-spans.js +1 -1
  66. package/dist/components/trace-viewer/util/use-trackpad-zoom.js +1 -1
  67. package/dist/components/trace-viewer/worker.js +1 -1
  68. package/dist/components/trace-viewer-new.js +1 -1
  69. package/dist/components/ui/alert.js +1 -1
  70. package/dist/components/ui/button.d.ts +10 -0
  71. package/dist/components/ui/button.d.ts.map +1 -0
  72. package/dist/components/ui/button.js +39 -0
  73. package/dist/components/ui/card.js +1 -1
  74. package/dist/components/ui/data-inspector.d.ts +1 -0
  75. package/dist/components/ui/data-inspector.d.ts.map +1 -1
  76. package/dist/components/ui/data-inspector.js +4 -9
  77. package/dist/components/ui/decrypt-button.js +1 -1
  78. package/dist/components/ui/error-card.js +1 -1
  79. package/dist/components/ui/error-stack-block.d.ts.map +1 -1
  80. package/dist/components/ui/error-stack-block.js +4 -18
  81. package/dist/components/ui/inspector-theme.js +1 -1
  82. package/dist/components/ui/load-more-button.js +1 -1
  83. package/dist/components/ui/menu-dropdown.js +1 -1
  84. package/dist/components/ui/skeleton.js +1 -1
  85. package/dist/components/ui/spinner.js +1 -1
  86. package/dist/components/ui/timestamp-tooltip.js +1 -1
  87. package/dist/components/workflow-trace-view.js +1 -1
  88. package/dist/components/workflow-traces/event-colors.js +1 -1
  89. package/dist/components/workflow-traces/trace-colors.js +1 -1
  90. package/dist/components/workflow-traces/trace-span-construction.js +1 -1
  91. package/dist/components/workflow-traces/trace-time-utils.js +1 -1
  92. package/dist/hooks/use-dark-mode.js +1 -1
  93. package/dist/hooks/use-reduced-motion.d.ts +10 -0
  94. package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
  95. package/dist/hooks/use-reduced-motion.js +29 -0
  96. package/dist/index.js +1 -1
  97. package/dist/lib/event-analysis.js +1 -1
  98. package/dist/lib/event-materialization.js +1 -1
  99. package/dist/lib/hydration.js +1 -1
  100. package/dist/lib/stream-display.js +1 -1
  101. package/dist/lib/toast.js +1 -1
  102. package/dist/lib/trace-builder.js +1 -1
  103. package/dist/lib/utils.js +1 -1
  104. package/package.json +5 -5
  105. package/src/components/event-list-view.tsx +29 -13
  106. package/src/components/new-trace-viewer/components/copy-button.tsx +1 -1
  107. package/src/components/new-trace-viewer/components/event-list.tsx +2 -2
  108. package/src/components/new-trace-viewer/components/timeline.tsx +353 -192
  109. package/src/components/new-trace-viewer/detail-panel.tsx +1 -1
  110. package/src/components/new-trace-viewer/trace-viewer.tsx +93 -59
  111. package/src/components/new-trace-viewer/utils.ts +40 -8
  112. package/src/components/sidebar/attribute-panel.tsx +212 -235
  113. package/src/components/sidebar/copyable-data-block.tsx +49 -27
  114. package/src/components/sidebar/detail-card.tsx +119 -41
  115. package/src/components/sidebar/entity-detail-panel.tsx +28 -28
  116. package/src/components/sidebar/events-list.tsx +51 -79
  117. package/src/components/ui/button.tsx +61 -0
  118. package/src/components/ui/data-inspector.tsx +9 -18
  119. package/src/components/ui/error-stack-block.tsx +7 -26
  120. package/src/hooks/use-reduced-motion.ts +34 -0
  121. package/dist/components/error-boundary.js.map +0 -1
  122. package/dist/components/event-list-view.js.map +0 -1
  123. package/dist/components/hook-actions.js.map +0 -1
  124. package/dist/components/index.js.map +0 -1
  125. package/dist/components/new-trace-viewer/components/copy-button.js.map +0 -1
  126. package/dist/components/new-trace-viewer/components/event-list.js.map +0 -1
  127. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js.map +0 -1
  128. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js.map +0 -1
  129. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js.map +0 -1
  130. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js.map +0 -1
  131. package/dist/components/new-trace-viewer/components/split-pane.js.map +0 -1
  132. package/dist/components/new-trace-viewer/components/timeline.js.map +0 -1
  133. package/dist/components/new-trace-viewer/context.js.map +0 -1
  134. package/dist/components/new-trace-viewer/detail-panel.js.map +0 -1
  135. package/dist/components/new-trace-viewer/icons.js.map +0 -1
  136. package/dist/components/new-trace-viewer/trace-viewer.js.map +0 -1
  137. package/dist/components/new-trace-viewer/types.js.map +0 -1
  138. package/dist/components/new-trace-viewer/util/constants.js.map +0 -1
  139. package/dist/components/new-trace-viewer/utils.js.map +0 -1
  140. package/dist/components/run-trace-view.js.map +0 -1
  141. package/dist/components/sidebar/attribute-panel.js.map +0 -1
  142. package/dist/components/sidebar/conversation-view.js.map +0 -1
  143. package/dist/components/sidebar/copyable-data-block.js.map +0 -1
  144. package/dist/components/sidebar/detail-card.js.map +0 -1
  145. package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
  146. package/dist/components/sidebar/events-list.js.map +0 -1
  147. package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
  148. package/dist/components/sidebar/sidebar-data-context.js.map +0 -1
  149. package/dist/components/stream-viewer.js.map +0 -1
  150. package/dist/components/trace-viewer/components/map.js.map +0 -1
  151. package/dist/components/trace-viewer/components/markers.js.map +0 -1
  152. package/dist/components/trace-viewer/components/node.js.map +0 -1
  153. package/dist/components/trace-viewer/components/search-input.js.map +0 -1
  154. package/dist/components/trace-viewer/components/search.js.map +0 -1
  155. package/dist/components/trace-viewer/components/span-content.js.map +0 -1
  156. package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
  157. package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
  158. package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
  159. package/dist/components/trace-viewer/components/ui.js.map +0 -1
  160. package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
  161. package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
  162. package/dist/components/trace-viewer/context.js.map +0 -1
  163. package/dist/components/trace-viewer/index.js.map +0 -1
  164. package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
  165. package/dist/components/trace-viewer/types.js.map +0 -1
  166. package/dist/components/trace-viewer/util/constants.js.map +0 -1
  167. package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
  168. package/dist/components/trace-viewer/util/timing.js.map +0 -1
  169. package/dist/components/trace-viewer/util/tree.js.map +0 -1
  170. package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
  171. package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
  172. package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
  173. package/dist/components/trace-viewer/worker.js.map +0 -1
  174. package/dist/components/trace-viewer-new.js.map +0 -1
  175. package/dist/components/ui/alert.js.map +0 -1
  176. package/dist/components/ui/card.js.map +0 -1
  177. package/dist/components/ui/data-inspector.js.map +0 -1
  178. package/dist/components/ui/decrypt-button.js.map +0 -1
  179. package/dist/components/ui/error-card.js.map +0 -1
  180. package/dist/components/ui/error-stack-block.js.map +0 -1
  181. package/dist/components/ui/inspector-theme.js.map +0 -1
  182. package/dist/components/ui/load-more-button.js.map +0 -1
  183. package/dist/components/ui/menu-dropdown.js.map +0 -1
  184. package/dist/components/ui/skeleton.js.map +0 -1
  185. package/dist/components/ui/spinner.js.map +0 -1
  186. package/dist/components/ui/timestamp-tooltip.js.map +0 -1
  187. package/dist/components/workflow-trace-view.js.map +0 -1
  188. package/dist/components/workflow-traces/event-colors.js.map +0 -1
  189. package/dist/components/workflow-traces/trace-colors.js.map +0 -1
  190. package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
  191. package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
  192. package/dist/hooks/use-dark-mode.js.map +0 -1
  193. package/dist/index.js.map +0 -1
  194. package/dist/lib/event-analysis.js.map +0 -1
  195. package/dist/lib/event-materialization.js.map +0 -1
  196. package/dist/lib/hydration.js.map +0 -1
  197. package/dist/lib/stream-display.js.map +0 -1
  198. package/dist/lib/toast.js.map +0 -1
  199. package/dist/lib/trace-builder.js.map +0 -1
  200. package/dist/lib/utils.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"stream-viewer.js","sourceRoot":"","sources":["../../src/components/stream-viewer.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport React, { useEffect, useRef } from 'react';\nimport { Virtuoso, type VirtuosoHandle } from 'react-virtuoso';\nimport { DataInspector } from './ui/data-inspector';\nimport { Skeleton } from './ui/skeleton';\n\n// ──────────────────────────────────────────────────────────────────────────\n// Types\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface StreamChunk {\n id: number;\n value: unknown;\n}\n\ntype Chunk = StreamChunk;\n\ninterface StreamViewerProps {\n streamId: string;\n chunks: Chunk[];\n isLive: boolean;\n error?: string | null;\n /** True while the initial stream connection is being established */\n isLoading?: boolean;\n /** Called when the user scrolls near the bottom, for triggering pagination */\n onScrollEnd?: () => void;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Chunk row — memoized to prevent remounts during polling\n// ──────────────────────────────────────────────────────────────────────────\n\nconst ChunkRow = React.memo(function ChunkRow({\n chunk,\n index,\n}: {\n chunk: Chunk;\n index: number;\n}) {\n return (\n <div\n className=\"text-[11px] rounded-md border p-3\"\n style={{\n borderColor: 'var(--ds-gray-300)',\n backgroundColor: 'var(--ds-gray-100)',\n }}\n >\n <div className=\"flex items-start gap-2\">\n <span\n className=\"select-none pt-px\"\n style={{ color: 'var(--ds-gray-500)' }}\n >\n [{index}]\n </span>\n <div className=\"min-w-0 flex-1\">\n {typeof chunk.value === 'string' ? (\n <span\n className=\"whitespace-pre-wrap break-words\"\n style={{ color: 'var(--ds-gray-1000)' }}\n >\n {chunk.value}\n </span>\n ) : (\n <DataInspector data={chunk.value} expandLevel={1} />\n )}\n </div>\n </div>\n </div>\n );\n});\n\n// ──────────────────────────────────────────────────────────────────────────\n// Skeleton loading\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction StreamSkeleton() {\n return (\n <div className=\"flex flex-col gap-3 animate-in fade-in\">\n <Skeleton style={{ width: 120, height: 16, borderRadius: 4 }} />\n {[1, 2, 3, 4].map((i) => (\n <Skeleton key={i} style={{ height: 56, borderRadius: 6 }} />\n ))}\n </div>\n );\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Main component\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * StreamViewer component that displays real-time stream data.\n * Each chunk is rendered with DataInspector for proper display\n * of complex types (Map, Set, Date, custom classes, etc.).\n */\nexport function StreamViewer({\n streamId: _streamId,\n chunks,\n isLive,\n error,\n isLoading,\n onScrollEnd,\n}: StreamViewerProps) {\n const virtuosoRef = useRef<VirtuosoHandle>(null);\n const prevChunkCountRef = useRef(0);\n\n // Auto-scroll to bottom when new chunks arrive (live streaming)\n useEffect(() => {\n if (chunks.length > prevChunkCountRef.current && chunks.length > 0) {\n virtuosoRef.current?.scrollToIndex({\n index: chunks.length - 1,\n align: 'end',\n });\n }\n prevChunkCountRef.current = chunks.length;\n }, [chunks.length]);\n\n // Show skeleton when loading and no chunks have arrived yet\n if (isLoading && chunks.length === 0) {\n return (\n <div className=\"flex flex-col h-full\">\n <StreamSkeleton />\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Live indicator */}\n {isLive && (\n <div className=\"flex items-center gap-1.5 mb-2 px-1\">\n <span\n className=\"inline-block w-2 h-2 rounded-full\"\n style={{ backgroundColor: 'var(--ds-green-600)' }}\n />\n <span className=\"text-xs\" style={{ color: 'var(--ds-green-700)' }}>\n Live\n </span>\n </div>\n )}\n\n {/* Header */}\n {chunks.length > 0 && (\n <div className=\"flex items-center gap-2 mb-2 px-1\">\n <span\n className=\"text-[13px] font-medium\"\n style={{ color: 'var(--ds-gray-900)' }}\n >\n Stream Chunks\n </span>\n <span\n className=\"text-xs tabular-nums\"\n style={{ color: 'var(--ds-gray-600)' }}\n >\n ({chunks.length})\n </span>\n </div>\n )}\n\n {/* Content */}\n <div className=\"flex-1 min-h-0\">\n {error ? (\n <div\n className=\"text-[11px] rounded-md border p-3\"\n style={{\n borderColor: 'var(--ds-red-300)',\n backgroundColor: 'var(--ds-red-100)',\n color: 'var(--ds-red-700)',\n }}\n >\n <div>Error reading stream:</div>\n <div>{error}</div>\n </div>\n ) : chunks.length === 0 ? (\n <div\n className=\"text-[11px] rounded-md border p-3\"\n style={{\n borderColor: 'var(--ds-gray-300)',\n backgroundColor: 'var(--ds-gray-100)',\n color: 'var(--ds-gray-600)',\n }}\n >\n {isLive ? 'Waiting for stream data...' : 'Stream is empty'}\n </div>\n ) : (\n <Virtuoso\n ref={virtuosoRef}\n totalCount={chunks.length}\n overscan={10}\n endReached={() => onScrollEnd?.()}\n itemContent={(index) => (\n <div style={{ paddingBottom: 8 }}>\n <ChunkRow chunk={chunks[index]} index={index} />\n </div>\n )}\n style={{ flex: 1, minHeight: 0 }}\n />\n )}\n </div>\n </div>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"map.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/map.tsx"],"names":[],"mappings":";AAAA,OAAO,EAEL,IAAI,EACJ,SAAS,EACT,eAAe,EACf,MAAM,EACN,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,MAAM,MAAM,4BAA4B,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE,MAAM,MAAM,GAAG,GAAW,EAAE;IAC1B,IAAI,kBAAkB,IAAI,UAAU,EAAE,CAAC;QACrC,OAAO,UAAU,CAAC,gBAAgB,IAAI,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,GAAW,EAAE;IAC1B,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAClC,eAAe,CAAC,GAAG,EAAE;QACnB,MAAM,QAAQ,GAAG,GAAS,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,UAAU,CAAC,gBAAgB,GAAG,OAAO,CAAC,CAAC;QACrD,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC3C,QAAQ,EAAE,CAAC;QAEX,OAAO,GAAG,EAAE;YACV,KAAK,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACV,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,OAAO,GAAG,gBAAgB,CAAC;AAEjC,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,OAAO,CAAC,EAC3C,WAAW,EACX,IAAI,EACJ,KAAK,GAKN;IACC,MAAM,EACJ,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,GAC5E,GAAG,cAAc,EAAE,CAAC;IACrB,MAAM,QAAQ,GAAG,SAAS,GAAG,gBAAgB,GAAG,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAElD,MAAM,UAAU,GACd,CAAC,SAAS,GAAG,CAAC,SAAS,GAAG,cAAc,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,aAAa,EAAE,SAAS,GAAG,KAAK,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CACzB,SAAS,EACT,CAAC,aAAa,GAAG,cAAc,CAAC,GAAG,UAAU,CAC9C,CAAC;IACF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,IAAyB,CAAC;QAE9B,MAAM,kBAAkB,GAAG,CAAC,MAA0B,EAAW,EAAE;YACjE,OAAO,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAqB,CAAC,CAAC,CAAC;QACxE,CAAC,CAAC;QAEF,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI;gBAAE,OAAO;YAC7B,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC;YACtC,IAAI,CAAC,SAAS;gBAAE,OAAO;YAEvB,MAAM,CAAC,GAAG,OAAO,GAAG,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;YACjD,SAAS,CAAC,UAAU,GAAG,CAAC,GAAG,UAAU,CAAC;QACxC,CAAC,CAAC;QAEF,MAAM,aAAa,GAAG,CAAC,KAAmB,EAAQ,EAAE;YAClD,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC;YACtB,oBAAoB,CAAC,SAAS,CAAC,CAAC;YAChC,SAAS,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC7C,CAAC,CAAC;QAEF,MAAM,aAAa,GAAG,CAAC,KAAmB,EAAQ,EAAE;YAClD,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC;gBAAE,OAAO;YAC9C,MAAM,GAAG,IAAI,CAAC;YACd,IAAI,GAAG,YAAY,CAAC,OAAO,EAAE,qBAAqB,EAAE,CAAC;YACrD,aAAa,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC;QAEF,MAAM,WAAW,GAAG,GAAS,EAAE;YAC7B,MAAM,GAAG,KAAK,CAAC;YACf,IAAI,GAAG,SAAS,CAAC;QACnB,CAAC,CAAC;QAEF,MAAM,YAAY,GAAG,CAAC,KAAiB,EAAQ,EAAE;YAC/C,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC;gBAAE,OAAO;YAC9C,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrB,KAAK,CAAC,cAAc,EAAE,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;QACF,MAAM,WAAW,GAAG,CAAC,KAAiB,EAAQ,EAAE;YAC9C,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrB,KAAK,CAAC,cAAc,EAAE,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACtD,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACtD,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAClD,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC7C,MAAM,CAAC,gBAAgB,CAAC,YAAY,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACxE,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAEtE,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;YACzD,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;YACzD,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YACrD,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YAChD,MAAM,CAAC,mBAAmB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YACrD,oBAAoB,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IAE1C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;QACjC,MAAM,GAAG,GAAG,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG;YAAE,OAAO;QAE5B,MAAM,MAAM,GAAG,GAAS,EAAE;YACxB,GAAG,CAAC,cAAc,EAAE,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACjD,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAEpB,MAAM,GAAG,GAAG,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,CAAC,CAAC;YACjB,MAAM,KAAK,GAAG,CAAC,QAAQ,GAAG,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YAEvD,kCAAkC;YAClC,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC;YACvB,GAAG,CAAC,SAAS,EAAE,CAAC;YAChB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;oBACvB,MAAM,CAAC,GAAG,OAAO,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;oBACpD,IAAI,CAAC,IAAI,UAAU,GAAG,MAAM,GAAG,OAAO;wBAAE,MAAM;oBAE9C,MAAM,CAAC,GAAG,OAAO,GAAG,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;oBAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;oBAEpC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;YACD,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAEhD,OAAO,GAAG,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;IAEhC,MAAM,QAAQ,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC9C,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,GAClD,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC9B,eAAe,CAAC,GAAG,EAAE;QACnB,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC;QACtC,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,aAAa,CACX,WAAW,EACX,cAAc,OAAO,GAAG,SAAS,CAAC,UAAU,GAAG,UAAU,KAAK,CAC/D,CAAC;QACJ,CAAC,CAAC;QACF,OAAO,EAAE,CAAC;QAEV,MAAM,QAAQ,GAAG,GAAS,EAAE;YAC1B,oBAAoB,CAAC,SAAS,CAAC,CAAC;YAChC,SAAS,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC7C,CAAC,CAAC;QACF,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAE/C,OAAO,GAAG,EAAE;YACV,oBAAoB,CAAC,SAAS,CAAC,CAAC;YAChC,SAAS,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACpD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;IAE7C,OAAO,CACL,eACE,SAAS,EAAE,MAAM,CAAC,YAAY,EAC9B,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE;YACL,KAAK,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM;YACzC,MAAM,EAAE,UAAU;SACnB,aAED,iBACE,SAAS,EAAE,MAAM,CAAC,SAAS,EAC3B,MAAM,EAAE,UAAU,GAAG,GAAG,EACxB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,EAC9C,KAAK,EAAE,QAAQ,GAAG,GAAG,GACrB,EACF,cACE,SAAS,EAAE,MAAM,CAAC,QAAQ,EAC1B,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE;oBACL,SAAS,EAAE,UAAU,CAAC,SAAS;oBAC/B,KAAK,EACH,UAAU,GAAG,CAAC;wBACZ,CAAC,CAAC,UAAU;wBACZ,CAAC,CAAC,eAAe,gBAAgB,GAAG,CAAC,KAAK;oBAC9C,GAAG,EAAE,CAAC;oBACN,MAAM,EAAE,UAAU,GAAG,CAAC;iBACvB,GACD,IACE,CACP,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import {\n type MutableRefObject,\n memo,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { useTraceViewer } from '../context';\nimport styles from '../trace-viewer.module.css';\nimport type { VisibleSpan } from '../types';\nimport { MAP_HEIGHT, TIMELINE_PADDING } from '../util/constants';\nimport { useImmediateStyle } from '../util/use-immediate-style';\n\nconst getDpi = (): number => {\n if ('devicePixelRatio' in globalThis) {\n return globalThis.devicePixelRatio || 1;\n }\n return 1;\n};\n\nconst useDpi = (): number => {\n const [dpi, setDpi] = useState(1);\n useLayoutEffect(() => {\n const onChange = (): void => setDpi(getDpi());\n const media = matchMedia(`(resolution: ${dpi}dppx)`);\n media.addEventListener('change', onChange);\n onChange();\n\n return () => {\n media.removeEventListener('change', onChange);\n };\n }, [dpi]);\n return dpi;\n};\n\nconst padding = TIMELINE_PADDING;\n\nexport const MiniMap = memo(function MiniMap({\n timelineRef,\n rows,\n scale,\n}: {\n timelineRef: MutableRefObject<HTMLDivElement | null>;\n rows: VisibleSpan[][];\n scale: number;\n}) {\n const {\n state: { root, baseScale, timelineWidth, width: fullWidth, scrollbarWidth },\n } = useTraceViewer();\n const mapWidth = fullWidth + TIMELINE_PADDING * 2;\n const dpi = useDpi();\n const containerRef = useRef<HTMLDivElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n\n const thumbRatio =\n (fullWidth / (fullWidth - scrollbarWidth)) *\n Math.min(fullWidth / timelineWidth, baseScale / scale);\n const thumbWidth = Math.min(\n fullWidth,\n (timelineWidth - scrollbarWidth) * thumbRatio\n );\n useEffect(() => {\n let isHeld = false;\n let clientX = 0;\n let rect: DOMRect | undefined;\n\n const isValidEventTarget = (target: EventTarget | null): boolean => {\n return Boolean(containerRef.current?.contains(target as HTMLElement));\n };\n\n let nextFrame = 0;\n const onFrame = (): void => {\n if (!isHeld || !rect) return;\n const $timeline = timelineRef.current;\n if (!$timeline) return;\n\n const x = clientX - thumbWidth * 0.5 - rect.left;\n $timeline.scrollLeft = x / thumbRatio;\n };\n\n const onPointerMove = (event: PointerEvent): void => {\n ({ clientX } = event);\n cancelAnimationFrame(nextFrame);\n nextFrame = requestAnimationFrame(onFrame);\n };\n\n const onPointerDown = (event: PointerEvent): void => {\n if (!isValidEventTarget(event.target)) return;\n isHeld = true;\n rect = containerRef.current?.getBoundingClientRect();\n onPointerMove(event);\n };\n\n const onPointerUp = (): void => {\n isHeld = false;\n rect = undefined;\n };\n\n const onTouchStart = (event: TouchEvent): void => {\n if (!isValidEventTarget(event.target)) return;\n if (event.cancelable) {\n event.preventDefault();\n }\n };\n const onTouchMove = (event: TouchEvent): void => {\n if (!isHeld) return;\n if (event.cancelable) {\n event.preventDefault();\n }\n };\n\n window.addEventListener('pointerdown', onPointerDown);\n window.addEventListener('pointermove', onPointerMove);\n window.addEventListener('pointerup', onPointerUp);\n window.addEventListener('blur', onPointerUp);\n window.addEventListener('touchstart', onTouchStart, { passive: false });\n window.addEventListener('touchmove', onTouchMove, { passive: false });\n\n return () => {\n window.removeEventListener('pointerdown', onPointerDown);\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', onPointerUp);\n window.removeEventListener('blur', onPointerUp);\n window.removeEventListener('touchstart', onTouchStart);\n window.removeEventListener('touchmove', onTouchMove);\n cancelAnimationFrame(nextFrame);\n };\n }, [timelineRef, thumbRatio, thumbWidth]);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const ctx = canvas?.getContext('2d');\n if (!canvas || !ctx) return;\n\n const render = (): void => {\n ctx.resetTransform();\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.scale(dpi, dpi);\n\n const gap = 1;\n const height = 3;\n const ratio = (mapWidth - padding * 2) / root.duration;\n\n // TODO: fill spans based on depth\n ctx.fillStyle = '#ccc';\n ctx.beginPath();\n for (const row of rows) {\n for (const span of row) {\n const y = padding - gap + (gap + height) * span.row;\n if (y >= MAP_HEIGHT - height - padding) break;\n\n const x = padding + (span.startTime - root.startTime) * ratio;\n const width = span.duration * ratio;\n\n ctx.roundRect(x, y, width, height, height);\n }\n }\n ctx.fill();\n };\n\n const nextFrame = requestAnimationFrame(render);\n\n return () => cancelAnimationFrame(nextFrame);\n }, [dpi, root, mapWidth, rows]);\n\n const thumbRef = useRef<HTMLDivElement>(null);\n const { style: thumbStyle, setStyle: setThumbStyle } =\n useImmediateStyle(thumbRef);\n useLayoutEffect(() => {\n const $timeline = timelineRef.current;\n if (!$timeline) return;\n\n let nextFrame = 0;\n const onFrame = (): void => {\n setThumbStyle(\n 'transform',\n `translateX(${padding + $timeline.scrollLeft * thumbRatio}px)`\n );\n };\n onFrame();\n\n const onScroll = (): void => {\n cancelAnimationFrame(nextFrame);\n nextFrame = requestAnimationFrame(onFrame);\n };\n $timeline.addEventListener('scroll', onScroll);\n\n return () => {\n cancelAnimationFrame(nextFrame);\n $timeline.removeEventListener('scroll', onScroll);\n };\n }, [timelineRef, thumbRatio, setThumbStyle]);\n\n return (\n <div\n className={styles.mapContainer}\n ref={containerRef}\n style={{\n width: thumbWidth > 0 ? mapWidth : '100%',\n height: MAP_HEIGHT,\n }}\n >\n <canvas\n className={styles.mapCanvas}\n height={MAP_HEIGHT * dpi}\n ref={canvasRef}\n style={{ width: mapWidth, height: MAP_HEIGHT }}\n width={mapWidth * dpi}\n />\n <div\n className={styles.mapThumb}\n ref={thumbRef}\n style={{\n transform: thumbStyle.transform,\n width:\n thumbWidth > 0\n ? thumbWidth\n : `calc(100% - ${TIMELINE_PADDING * 2}px)`,\n top: 2,\n height: MAP_HEIGHT - 4,\n }}\n />\n </div>\n );\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"markers.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/markers.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { clsx } from 'clsx';\nimport type {\n CSSProperties,\n Dispatch,\n MutableRefObject,\n ReactNode,\n} from 'react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { type TraceViewerAction, useTraceViewer } from '../context';\nimport styles from '../trace-viewer.module.css';\nimport type {\n MemoCache,\n RootNode,\n ScrollSnapshot,\n VisibleSpan,\n VisibleSpanEvent,\n} from '../types';\nimport {\n MARKER_HEIGHT,\n ROW_HEIGHT,\n ROW_PADDING,\n TIMELINE_PADDING,\n} from '../util/constants';\nimport {\n formatDurationForTimeline,\n formatTimeSelection,\n formatWallClockTime,\n} from '../util/timing';\nimport { useImmediateStyle } from '../util/use-immediate-style';\nimport { useTrackpadZoom } from '../util/use-trackpad-zoom';\n\n/**\n * Snap a raw duration to the nearest \"nice\" number in the 1-2-5 × 10^n\n * sequence (e.g. …, 0.5, 1, 2, 5, 10, 20, 50, 100, …).\n */\nfunction snapToNice(raw: number): number {\n if (raw <= 0) return 1;\n const log10 = Math.floor(Math.log10(raw));\n const pow = 10 ** log10;\n const normalized = raw / pow;\n\n if (normalized <= 1.5) return pow;\n if (normalized <= 3.5) return 2 * pow;\n if (normalized <= 7.5) return 5 * pow;\n return 10 * pow;\n}\n\nexport function Markers({\n scale,\n isLive = false,\n}: {\n scale: number;\n isLive?: boolean;\n}): ReactNode {\n const {\n state: { root },\n } = useTraceViewer();\n // Force a re-render every second when live to pick up new tick marks.\n // The markers container width is grown at 60fps by useLiveTick;\n // this interval only ensures the marker *labels* stay current.\n const [, forceMarkerUpdate] = useState(0);\n useEffect(() => {\n if (!isLive) return;\n const id = setInterval(() => forceMarkerUpdate((v) => v + 1), 1000);\n return () => clearInterval(id);\n }, [isLive]);\n\n const fullDuration = root.duration;\n\n // Calculate a marker interval that gives reasonable spacing at any zoom level.\n // We target ~50px per notch mark; labels appear on every Nth notch via labelSpacing.\n // When scale is <= 0 (e.g. the initial -1 sentinel), fall back to a safe default\n // to avoid generating an absurd number of markers.\n const effectiveScale =\n scale > 0 ? scale : fullDuration > 0 ? 1 / fullDuration : 1;\n const targetNotchPx = 50;\n let markerDuration = snapToNice(targetNotchPx / effectiveScale);\n markerDuration = Math.max(1, markerDuration);\n let markerWidth = markerDuration * effectiveScale;\n\n // Cap marker count to avoid creating too many DOM elements at extreme zoom\n // on very long traces. Only the visible portion is shown on screen anyway.\n const MAX_MARKERS = 1000;\n if (fullDuration / markerDuration > MAX_MARKERS) {\n markerDuration = snapToNice(fullDuration / MAX_MARKERS);\n markerWidth = markerDuration * effectiveScale;\n }\n const markerCount = Math.ceil(fullDuration / markerDuration);\n\n // How often labels should appear for markers, e.g. 3 === one label for every third marker\n const labelSpacing = Math.ceil(100 / markerWidth) || 1;\n\n return (\n <div className={styles.markersContainer}>\n <div\n aria-hidden\n className={styles.markers}\n style={\n {\n width: Math.floor(root.duration * scale + 15),\n visibility: scale !== -1 ? 'visible' : 'hidden',\n '--marker-width': `${markerWidth}px`,\n } as CSSProperties\n }\n >\n {new Array(markerCount).fill(null).map((_, i) => {\n const hasLabel = i % labelSpacing === 0;\n return (\n <span\n className={clsx(styles.marker, !hasLabel && styles.notch)}\n key={String(i)}\n >\n {hasLabel ? (\n <span className={styles.markerLabel}>\n {formatDurationForTimeline(markerDuration * i)}\n <span className={styles.markerClockTime}>\n {formatWallClockTime(root.startTime + markerDuration * i)}\n </span>\n </span>\n ) : null}\n </span>\n );\n })}\n </div>\n </div>\n );\n}\n\nexport function EventMarkers({\n events,\n root,\n scale,\n}: {\n events: VisibleSpanEvent[];\n root: RootNode;\n scale: number;\n}): ReactNode {\n // Filter out events that should not show vertical lines (workflow-specific feature)\n const eventsWithVerticalLines = useMemo(\n () => events.filter((x) => x.event.showVerticalLine !== false),\n [events]\n );\n\n return (\n <div className={styles.eventMarkersContainer}>\n <div\n aria-hidden\n className={styles.eventMarkers}\n style={\n {\n width: Math.floor(root.duration * scale),\n } as CSSProperties\n }\n >\n {eventsWithVerticalLines.map((x) => {\n return (\n <span\n className={clsx(styles.eventMarker)}\n key={x.key}\n style={{\n left: Math.floor((x.timestamp - root.startTime) * scale),\n ...(x.event.color && { borderLeftColor: x.event.color }),\n }}\n />\n );\n })}\n </div>\n </div>\n );\n}\n\nconst HOVER_OVERSCAN = 2;\n\ninterface TrackpadZoom {\n anchorX: number;\n anchorT: number;\n}\n\nexport function CursorMarker({\n memoCacheRef,\n timelineRef,\n root,\n spans,\n events,\n scale,\n dispatch,\n scrollSnapshotRef,\n}: {\n memoCacheRef: MutableRefObject<MemoCache>;\n timelineRef: MutableRefObject<HTMLDivElement | null>;\n root: RootNode;\n spans: VisibleSpan[];\n events: VisibleSpanEvent[];\n scale: number;\n dispatch: Dispatch<TraceViewerAction>;\n scrollSnapshotRef: MutableRefObject<ScrollSnapshot | undefined>;\n}): ReactNode {\n const hasEnteredRef = useRef(false);\n const spansRef = useRef(spans);\n spansRef.current = spans;\n const eventsRef = useRef(events);\n eventsRef.current = events;\n const labelRef = useRef<HTMLDivElement>(null);\n const { style: labelStyle, setStyle: setLabelStyle } =\n useImmediateStyle(labelRef);\n const labelTextRef = useRef<HTMLDivElement>(null);\n\n const ref = useRef<HTMLDivElement>(null);\n const { style, setStyle } = useImmediateStyle(ref);\n const rectRef = useRef<DOMRect>(undefined);\n\n const selectionRef = useRef<HTMLDivElement>(null);\n const { style: selectionStyle, setStyle: setSelectionStyle } =\n useImmediateStyle(selectionRef);\n\n const xRef = useRef(0);\n useEffect(() => {\n const $timeline = timelineRef.current;\n if (!$timeline) return;\n\n let x = xRef.current;\n let xStart = 0;\n let isDragging = false;\n let isExternalDrag = false;\n let hasMoved = false;\n let isRightClick = false;\n let scrollX = 0;\n let scrollY = 0;\n const hoverStartT = Date.now() + 500;\n const updateRect = (): void => {\n if (rectRef.current) return;\n rectRef.current = $timeline.getBoundingClientRect();\n };\n\n const getRowFromY = (y: number): number => {\n if (!rectRef.current) return 0;\n return (\n (y - MARKER_HEIGHT - TIMELINE_PADDING) / (ROW_HEIGHT + ROW_PADDING)\n );\n };\n\n const removeHover = (): void => {\n const cache = memoCacheRef.current;\n // Remove hover styling from any elements that have it\n for (const span of spansRef.current) {\n if (!span.isHovered) continue;\n span.isHovered = false;\n cache.set(span.span.spanId, {});\n }\n dispatch({\n type: 'forceRender',\n });\n };\n\n let nextFrame = 0;\n const onFrame = (): void => {\n if (!hasEnteredRef.current) return;\n if (!rectRef.current) updateRect();\n const rect = rectRef.current;\n if (!rect) return;\n\n const { scrollLeft, scrollTop } = $timeline;\n\n const left = Math.max(\n 0,\n Math.min(\n x + scrollLeft - rect.left - TIMELINE_PADDING,\n root.duration * scale\n )\n );\n const leftStyle = `${left - scrollLeft + TIMELINE_PADDING}px`;\n setStyle('left', leftStyle);\n setLabelStyle('left', leftStyle);\n\n const t = root.startTime + left / scale;\n const labelT = t - root.startTime;\n if (labelT < 0 || labelT > root.duration) {\n labelTextRef.current?.removeAttribute('data-text');\n } else {\n labelTextRef.current?.setAttribute(\n 'data-text',\n formatTimeSelection(labelT)\n );\n }\n\n if (isDragging) {\n const xDelta = x - xStart;\n const width = Math.abs(xDelta);\n if (!hasMoved) {\n if (width < 4) return;\n hasMoved = true;\n setSelectionStyle('display', 'flex');\n removeHover();\n }\n\n if (xDelta > 0) {\n setSelectionStyle('left', '');\n setSelectionStyle('right', '0');\n } else {\n setSelectionStyle('left', '0');\n setSelectionStyle('right', '');\n }\n setSelectionStyle('width', `${width}px`);\n\n const leftStart = Math.max(\n 0,\n Math.min(\n xStart + scrollLeft - rect.left - TIMELINE_PADDING,\n root.duration * scale\n )\n );\n const labelTStart = leftStart / scale;\n let t1: number;\n let t2: number;\n if (labelTStart < labelT) {\n t1 = labelTStart;\n t2 = labelT;\n } else {\n t1 = labelT;\n t2 = labelTStart;\n }\n selectionRef.current?.setAttribute(\n 'data-range',\n `${formatTimeSelection(t1)} — ${formatTimeSelection(t2)}`\n );\n selectionRef.current?.setAttribute(\n 'data-duration',\n `${formatTimeSelection(t2 - t1)} selected`\n );\n }\n\n if (Date.now() < hoverStartT) {\n nextFrame = requestAnimationFrame(onFrame);\n return;\n }\n\n if (scrollLeft !== scrollX || scrollTop !== scrollY) {\n scrollX = scrollLeft;\n scrollY = scrollTop;\n nextFrame = requestAnimationFrame(onFrame);\n return;\n }\n\n if (x - rect.left < 128) {\n labelTextRef.current?.setAttribute('data-align', 'left');\n } else if (x - rect.left > rect.width - 128) {\n labelTextRef.current?.setAttribute('data-align', 'right');\n } else {\n labelTextRef.current?.removeAttribute('data-align');\n }\n\n if (!hasMoved && !isExternalDrag) {\n const cache = memoCacheRef.current;\n\n // Span Hover\n const rowMin = getRowFromY(scrollTop) - HOVER_OVERSCAN;\n const rowMax = getRowFromY(scrollTop + rect.height) + HOVER_OVERSCAN;\n for (const span of spansRef.current) {\n const isHovered =\n span.row >= rowMin &&\n span.row <= rowMax &&\n t >= span.startTime &&\n t <= span.endTime;\n if (span.isHovered === isHovered) continue;\n span.isHovered = isHovered;\n cache.set(span.span.spanId, {});\n }\n\n // Event Hover — only show the nearest event when multiple overlap\n const eventSpreadPx = 12;\n const eventSpreadMs = eventSpreadPx / scale;\n let closestEvent: (typeof eventsRef.current)[number] | null = null;\n let closestDist = Infinity;\n for (const event of eventsRef.current) {\n const dist = Math.abs(event.timestamp - t);\n if (dist <= eventSpreadMs && dist < closestDist) {\n closestDist = dist;\n closestEvent = event;\n }\n }\n for (const event of eventsRef.current) {\n const isHovered = event === closestEvent;\n if (event.isHovered === isHovered) continue;\n event.isHovered = isHovered;\n const $event = event.ref?.current;\n if (!$event) continue;\n $event.setAttribute('data-hovered', String(isHovered));\n }\n\n dispatch({\n type: 'forceRender',\n });\n }\n };\n nextFrame = requestAnimationFrame(onFrame);\n\n const onPointerEnter = (event: PointerEvent): void => {\n if (event.pointerType !== 'mouse') return;\n hasEnteredRef.current = true;\n };\n const onPointerLeave = (): void => {\n if (!hasEnteredRef.current) return;\n hasEnteredRef.current = false;\n removeHover();\n };\n\n const onMouseMove = ({ clientX }: MouseEvent): void => {\n x = clientX;\n xRef.current = x;\n cancelAnimationFrame(nextFrame);\n nextFrame = requestAnimationFrame(onFrame);\n };\n\n const onContextMenu = (event: MouseEvent): void => {\n event.preventDefault();\n };\n const onMouseDown = (event: MouseEvent): void => {\n if (event.button === 2) {\n isRightClick = true;\n event.preventDefault();\n } else if (event.button !== 0) {\n return;\n } else {\n isRightClick = false;\n }\n if (timelineRef.current?.contains(event.target as HTMLElement)) {\n xStart = x;\n isDragging = true;\n } else {\n isExternalDrag = true;\n requestAnimationFrame(removeHover);\n }\n };\n const onMouseUp = (event: Event): void => {\n isExternalDrag = false;\n\n if (!isDragging) return;\n isDragging = false;\n\n if (!hasMoved) return;\n hasMoved = false;\n setSelectionStyle('display', '');\n setSelectionStyle('left', '');\n setSelectionStyle('right', '');\n setSelectionStyle('width', '');\n\n event.preventDefault();\n event.stopImmediatePropagation();\n\n if (isRightClick) {\n isRightClick = false;\n return;\n }\n\n if (!rectRef.current) updateRect();\n const rect = rectRef.current;\n if (!rect) return;\n\n const { scrollLeft } = $timeline;\n\n const start = Math.max(\n 0,\n Math.min(\n (xStart + scrollLeft - rect.left - TIMELINE_PADDING) / scale,\n root.duration\n )\n );\n const end = Math.max(\n 0,\n Math.min(\n (x + scrollLeft - rect.left - TIMELINE_PADDING) / scale,\n root.duration\n )\n );\n\n dispatch({\n type: 'scaleToRange',\n t1: start + root.startTime,\n t2: end + root.startTime,\n });\n };\n\n const onKeyDown = (event: KeyboardEvent): void => {\n if (!isDragging) return;\n if (event.key !== 'Escape') return;\n\n isRightClick = true;\n onMouseUp(event);\n };\n\n const onWindowScroll = (): void => {\n rectRef.current = undefined;\n trackpadZoomRef.current = undefined;\n cancelAnimationFrame(nextFrame);\n nextFrame = requestAnimationFrame(onFrame);\n };\n\n const onScroll = (): void => {\n cancelAnimationFrame(nextFrame);\n nextFrame = requestAnimationFrame(onFrame);\n };\n\n const observer = new ResizeObserver(() => {\n // NOTE: I tried to use the entry from this to immediately set the rect,\n // but for some reason it has different dimensions than the one from\n // .getBoundingClientRect()\n rectRef.current = undefined;\n });\n observer.observe($timeline);\n\n window.addEventListener('mousemove', onMouseMove);\n $timeline.addEventListener('contextmenu', onContextMenu);\n window.addEventListener('mousedown', onMouseDown);\n window.addEventListener('mouseup', onMouseUp);\n window.addEventListener('blur', onMouseUp);\n window.addEventListener('keydown', onKeyDown, true);\n window.addEventListener('scroll', onWindowScroll);\n $timeline.addEventListener('scroll', onScroll);\n $timeline.addEventListener('pointerenter', onPointerEnter);\n $timeline.addEventListener('pointerleave', onPointerLeave);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('mousemove', onMouseMove);\n $timeline.removeEventListener('contextmenu', onContextMenu);\n window.removeEventListener('mousedown', onMouseDown);\n window.removeEventListener('mouseup', onMouseUp);\n window.removeEventListener('blur', onMouseUp);\n window.removeEventListener('keydown', onKeyDown, true);\n window.removeEventListener('scroll', onWindowScroll);\n $timeline.removeEventListener('scroll', onScroll);\n $timeline.removeEventListener('pointerenter', onPointerEnter);\n $timeline.removeEventListener('pointerleave', onPointerLeave);\n cancelAnimationFrame(nextFrame);\n xRef.current = x;\n removeHover();\n };\n }, [\n dispatch,\n root,\n scale,\n setStyle,\n setLabelStyle,\n setSelectionStyle,\n memoCacheRef,\n timelineRef,\n scrollSnapshotRef,\n ]);\n\n const trackpadZoomRef = useRef<TrackpadZoom>(undefined);\n useTrackpadZoom((delta) => {\n const $timeline = timelineRef.current;\n if (!$timeline) return;\n\n rectRef.current ??= $timeline.getBoundingClientRect();\n const rect = rectRef.current;\n const anchorX = Math.max(\n 0,\n Math.min(\n xRef.current - rect.left - TIMELINE_PADDING,\n rect.width - 2 * TIMELINE_PADDING\n )\n );\n\n let anchorT = 0;\n let existing = trackpadZoomRef.current;\n if (existing?.anchorX === anchorX) {\n anchorT = existing.anchorT;\n } else {\n anchorT = ($timeline.scrollLeft + anchorX) / scale;\n existing = {\n anchorT,\n anchorX,\n };\n trackpadZoomRef.current = existing;\n }\n\n dispatch({\n type: 'trackpadScale',\n delta: delta / 64,\n anchorT,\n anchorX,\n });\n });\n\n return (\n <>\n <div className={styles.cursorMarkerStickyParent}>\n <div\n className={styles.cursorMarkerLabelContainer}\n ref={labelRef}\n style={labelStyle}\n >\n <div className={styles.cursorMarkerLabel} ref={labelTextRef} />\n </div>\n </div>\n <div className={styles.cursorMarkerStickyParent}>\n <div className={styles.cursorMarkerContainer} ref={ref} style={style}>\n <div className={styles.cursorMarker}>\n <div\n className={styles.cursorSelection}\n ref={selectionRef}\n style={selectionStyle}\n />\n </div>\n </div>\n </div>\n </>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/node.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,MAAM,MAAM,4BAA4B,CAAC;AAUhD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAGL,eAAe,EACf,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,IAAc,EAAU,EAAE;IAC9D,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,aAAa,GAAG,CAAC,EAAc,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC;AAEF,SAAS,oBAAoB,CAC3B,YAA0B,EAC1B,IAAiB;IAEjB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,IAAI,CAAC,MAAM,EAAE,MAAM;QAAE,OAAO,SAAS,CAAC;IAEtC,QAAQ,YAAY,EAAE,CAAC;QACrB,KAAK,MAAM;YACT,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,GAAI,CAAC;gBAClC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;oBAC7C,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC7B,CAAC;YACH,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,KAAK,OAAO;YACV,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,GAAI,CAAC;gBAClC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;oBAC9C,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC7B,CAAC;YACH,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,KAAK,KAAK;YACR,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,GAAI,CAAC;gBAClC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;gBAClC,IACE,IAAI,KAAK,eAAe;oBACxB,IAAI,KAAK,YAAY;oBACrB,IAAI,KAAK,eAAe,EACxB,CAAC;oBACD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC7B,CAAC;YACH,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,KAAK,MAAM;YACT,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,GAAI,CAAC;gBAClC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;gBAClC,IAAI,IAAI,KAAK,gBAAgB,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;oBACxD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC7B,CAAC;gBACD,IAAI,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;oBACxD,OAAO,SAAS,CAAC;gBACnB,CAAC;YACH,CAAC;YACD,OAAO,SAAS,CAAC;QACnB;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,SAAS,CAAC,EAC/C,IAAI,EACJ,KAAK,EACL,KAAK,EACL,MAAM,GAAG,KAAK,EACd,iBAAiB,EACjB,KAAK,EACL,uBAAuB,EACvB,4BAA4B,GAY7B;IACC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACtB,KAAC,aAAa,IACZ,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAClC,4BAA4B,EAAE,4BAA4B,EAC1D,uBAAuB,EAAE,uBAAuB,EAEhD,IAAI,EAAE,CAAC,EACP,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,iBAAiB,IAL/B,CAAC,CAAC,IAAI,CAAC,MAAM,CAMlB,CACH,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,6EAA6E;AAC7E,0CAA0C;AAC1C,6EAA6E;AAE7E,SAAS,YAAY,CACnB,MAAkB,EAClB,IAAiB,EACjB,IAAc,EACd,KAAa;IAEb,mEAAmE;IACnE,0DAA0D;IAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC;IACnC,OAAO;QACL,kEAAkE;QAClE,cAAc,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI;QACtD,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;QAC7C,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK;QAC1C,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EACN,QAAQ,IAAI,CAAC,MAAM,CAAC,eAAe;YACjC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK;YACzC,CAAC,CAAC,SAAS;QACf,qBAAqB,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK;QAC1D,sBAAsB,EAAE,MAAM,CAAC,MAAM;QACrC,IAAI,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI;QACtD,KAAK,EAAE,MAAM,CAAC,eAAe;YAC3B,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK;YACvC,CAAC,CAAC,SAAS;QACb,GAAG,EAAE,MAAM,CAAC,GAAG;KACC,CAAC;AACrB,CAAC;AAED,6EAA6E;AAC7E,gBAAgB;AAChB,6EAA6E;AAE7E,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,aAAa,CAAC,EACvD,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,WAAW,GAAG,KAAK,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,4BAA4B,GAW7B;IACC,MAAM,GAAG,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;QACvB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IACtB,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE1C,kDAAkD;IAClD,MAAM,eAAe,GAAG,uBAAuB;QAC7C,CAAC,CAAC,uBAAuB,CAAC,IAAI,CAAC;QAC/B,CAAC,CAAC,EAAE,CAAC;IAEP,mEAAmE;IACnE,+CAA+C;IAC/C,MAAM,cAAc,GAAG,YAAY,KAAK,SAAS,CAAC;IAElD,2EAA2E;IAC3E,0EAA0E;IAC1E,iCAAiC;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,IAA2C,CAAC;IAC1E,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACnE,MAAM,gBAAgB,GAAG,iBAAiB,IAAI,IAAI,CAAC;IACnD,MAAM,iBAAiB,GACrB,YAAY,KAAK,MAAM;QACrB,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC;QAC3B,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACjC,MAAM,WAAW,GAAG,iBAAiB,IAAI,gBAAgB,CAAC;IAC1D,MAAM,MAAM,GAAG,WAAW,IAAI,cAAc,IAAI,CAAC,WAAW,CAAC;IAE7D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACvB,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;YAChC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACzB,CAAC,EAAE,GAAG,CAAC,CAAC;QACR,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,kBAAkB,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,iBAAiB,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,wBAAwB,GAAG,IAAI,CAAC,eAAe;QACnD,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,eAAe,CAAC;QACtC,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,UAAU,GACd,iBAAiB,IAAI,IAAI;QACvB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;QACrD,CAAC,CAAC,MAAM;YACN,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,kBAAkB,CAAC;YAC3D,CAAC,CAAC,iBAAiB,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB;QACzC,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG;QACf,GAAG,IAAI;QACP,SAAS,EAAE,kBAAkB;QAC7B,OAAO,EAAE,gBAAgB;QACzB,QAAQ,EAAE,iBAAiB;QAC3B,eAAe,EAAE,wBAAwB;KAC3B,CAAC;IACjB,MAAM,WAAW,GAAG,MAAM;QACxB,CAAC,CAAE;YACC,GAAG,QAAQ;YACX,QAAQ,EAAE,UAAU;YACpB,OAAO,EAAE,kBAAkB,GAAG,UAAU;SACzB;QACnB,CAAC,CAAC,QAAQ,CAAC;IACb,MAAM,WAAW,GACf,cAAc;QACd,eAAe,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,aAAa,CAC1B,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,KAAK,EACL,iBAAiB,CAClB,CAAC;IAEF,4EAA4E;IAC5E,wEAAwE;IACxE,wBAAwB;IACxB,uEAAuE;IACvE,2EAA2E;IAC3E,qEAAqE;IACrE,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,OAAO,GAAG,UAAU,CAAC;QAC3B,MAAM,eAAe,GAAG,OAAO,GAAG,KAAK,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,WAAW,GAAG,eAAe,CAAC;QACrC,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC;QACzB,MAAM,CAAC,OAAO,GAAG,eAAe,GAAG,EAAE,CAAC;QACtC,MAAM,CAAC,MAAM,GAAG,eAAe,IAAI,GAAG,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC;YAC3B,MAAM,CAAC,GAAG,GAAG,aAAa,GAAG,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,iEAAiE;IACjE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO;YAAE,OAAO;QAEpC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,IAAI,GAAG,GAAS,EAAE;YACtB,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;YACxB,IAAI,CAAC,GAAG;gBAAE,OAAO;YACjB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,CAAC;YAChD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;YACvC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC;YAC3B,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YAChD,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC;QACF,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,GAAG,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAAC;IAExC,MAAM,UAAU,GAAG,WAAW,CAAC;IAE/B,OAAO,CACL,8BACE,+BACc,GAAG,IAAI,CAAC,IAAI,MAAM,QAAQ,EAAE,EACxC,SAAS,EAAE,IAAI,CACb,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAC5B,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,EAC9B,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,EAClC,IAAI,CAAC,aAAa;oBAChB,CAAC,CAAC,MAAM,CAAC,cAAc;oBACvB,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAC/B,IAAI,CAAC,aAAa,KAAK,KAAK,IAAI,MAAM,CAAC,KAAK,EAC5C,eAAe,EACf,WAAW,IAAI,MAAM,CAAC,WAAW,CAClC,kBACa,IAAI,CAAC,MAAM,qBACR,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,qBACtC,MAAM,CAAC,eAAe,mBACxB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAC/C,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,CAAC,EACrD,IAAI,EAAC,QAAQ,YAEb,KAAC,WAAW,IACV,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,GACd,GACK,EACR,WAAW,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO;gBACpC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAC5B,KAAC,kBAAkB,IACjB,4BAA4B,EAAE,4BAA4B,EAC1D,KAAK,EAAE,CAAC,EAER,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,cAAc,IAJrB,CAAC,CAAC,GAAG,CAKV,CACH,CAAC;gBACJ,CAAC,CAAC,IAAI,IACP,CACJ,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,6EAA6E;AAC7E,qBAAqB;AACrB,6EAA6E;AAE7E,qDAAqD;AACrD,MAAM,eAAe,GAA2B;IAC9C,YAAY,EAAE,SAAS;IACvB,aAAa,EAAE,UAAU;IACzB,WAAW,EAAE,QAAQ;IACrB,YAAY,EAAE,SAAS;IACvB,aAAa,EAAE,UAAU;IACzB,aAAa,EAAE,UAAU;IACzB,YAAY,EAAE,eAAe;IAC7B,cAAc,EAAE,iBAAiB;IACjC,WAAW,EAAE,SAAS;IACtB,aAAa,EAAE,WAAW;IAC1B,UAAU,EAAE,YAAY;IACxB,cAAc,EAAE,WAAW;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,kBAAkB,CAAC,EACjE,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,4BAA4B,EAC5B,UAAU,GAAG,KAAK,GAQnB;IACC,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEzC,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC;QAChB,OAAO,GAAG,EAAE;YACV,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC;QACxB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,EACJ,KAAK,EAAE,EAAE,IAAI,EAAE,GAChB,GAAG,KAAK,CAAC;IACV,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IACnE,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEzE,0DAA0D;IAC1D,qEAAqE;IACrE,yEAAyE;IACzE,MAAM,cAAc,GAClB,UAAU;QACV,CAAC,IAAI,KAAK,cAAc;YACtB,IAAI,KAAK,aAAa;YACtB,IAAI,KAAK,eAAe,CAAC,CAAC;IAC9B,MAAM,eAAe,GACnB,UAAU,IAAI,CAAC,IAAI,KAAK,gBAAgB,IAAI,IAAI,KAAK,eAAe,CAAC,CAAC;IAExE,IAAI,aAAa,GAAkB,IAAI,CAAC;IACxC,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,IAAI,CAAC,cAAc,IAAI,eAAe,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACvD,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAC5C,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CACpC,CAAC;QACF,MAAM,UAAU,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,CAAC,CAAC;QAE1E,IAAI,eAAe,EAAE,CAAC;YACpB,8CAA8C;YAC9C,IAAI,aAAa,GAAkB,IAAI,CAAC;YACxC,KAAK,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACzC,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBACtD,aAAa,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;oBAC9C,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,aAAa,GAAG,cAAc,CAAC,KAAK,CAAC,SAAS,GAAG,aAAa,CAAC,CAAC;gBAChE,UAAU,GAAG,UAAU,CAAC;YAC1B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,iCAAiC;YACjC,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;YACnD,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;YAC/D,aAAa,GAAG,cAAc,CAAC,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;YAC1D,UAAU,GAAG,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;QAChE,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IACxD,MAAM,GAAG,GAAG,aAAa,GAAG,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;IAClE,MAAM,aAAa,GACjB,IAAI,CAAC,QAAQ,IAAI,CAAC;QAClB,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;IAE3D,kDAAkD;IAClD,MAAM,eAAe,GAAG,4BAA4B;QAClD,CAAC,CAAC,4BAA4B,CAAC,KAAK,CAAC;QACrC,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,CACL,eACE,KAAK,EACH,aAAa;YACX,CAAC,CAAC,GAAG,YAAY,IAAI,SAAS,KAAK,UAAU,IAAI,aAAa,EAAE;YAChE,CAAC,CAAC,GAAG,YAAY,IAAI,SAAS,EAAE,EAEpC,SAAS,EAAE,IAAI,CACb,MAAM,CAAC,aAAa,EACpB,eAAe,EACf,UAAU,IAAI,MAAM,CAAC,cAAc,EACnC,IAAI,CAAC,aAAa;YAChB,CAAC,CAAC,MAAM,CAAC,cAAc;YACvB,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAC/B,IAAI,CAAC,aAAa,KAAK,KAAK,IAAI,MAAM,CAAC,KAAK,CAC7C,kBACa,KAAK,CAAC,SAAS,EAC7B,GAAG,EAAE,GAAG,EACR,KAAK,EACH;YACE,IAAI;YACJ,GAAG;SACa,aAGpB,cACE,SAAS,EAAE,IAAI,CACb,MAAM,CAAC,SAAS,EAChB,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CACpD,YAEA,UAAU,CAAC,CAAC,CAAC,CACZ,8BACE,eAAM,SAAS,EAAE,MAAM,CAAC,SAAS,YAAG,YAAY,GAAQ,EACxD,eAAM,SAAS,EAAE,MAAM,CAAC,cAAc,YAAG,SAAS,GAAQ,EACzD,aAAa,CAAC,CAAC,CAAC,CACf,8BACE,eAAM,SAAS,EAAE,MAAM,CAAC,SAAS,YAAG,UAAU,GAAQ,EACtD,eAAM,SAAS,EAAE,MAAM,CAAC,cAAc,YAAG,aAAa,GAAQ,IAC7D,CACJ,CAAC,CAAC,CAAC,IAAI,IACP,CACJ,CAAC,CAAC,CAAC,CACF,8BACE,eAAM,SAAS,EAAE,MAAM,CAAC,SAAS,YAAG,IAAI,GAAQ,EAChD,eAAM,SAAS,EAAE,MAAM,CAAC,cAAc,YAAG,SAAS,GAAQ,IACzD,CACJ,GACG,EACL,UAAU,CAAC,CAAC,CAAC,CACZ,cAAK,SAAS,EAAE,MAAM,CAAC,YAAY,GAAI,CACxC,CAAC,CAAC,CAAC,CACF,cAAK,SAAS,EAAE,MAAM,CAAC,YAAY,GAAI,CACxC,IACG,CACP,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["'use client';\n\nimport { clsx } from 'clsx';\nimport type { CSSProperties, MutableRefObject, ReactNode } from 'react';\nimport { memo, useEffect, useRef, useState } from 'react';\nimport styles from '../trace-viewer.module.css';\nimport type {\n MemoCache,\n MemoCacheKey,\n RootNode,\n ScrollSnapshot,\n SpanNode,\n VisibleSpan,\n VisibleSpanEvent,\n} from '../types';\nimport { MARKER_HEIGHT, ROW_HEIGHT, ROW_PADDING } from '../util/constants';\nimport { formatDuration, getHighResInMs } from '../util/timing';\nimport { SpanContent } from './span-content';\nimport { computeSegments } from './span-segments';\nimport {\n type ResourceType,\n type SpanLayout,\n getResourceType,\n getSpanLayout,\n} from './span-strategies';\n\nexport const getSpanColorClassName = (node: SpanNode): string => {\n if (node.isVercel) return String(styles.colorVercel);\n return String(styles[`color${node.resourceIndex % 5}` as 'color0']);\n};\n\nfunction getTerminalTimestamp(\n resourceType: ResourceType,\n node: VisibleSpan\n): number | undefined {\n const events = node.events;\n if (!events?.length) return undefined;\n\n switch (resourceType) {\n case 'hook':\n for (let i = events.length; i--; ) {\n if (events[i].event.name === 'hook_disposed') {\n return events[i].timestamp;\n }\n }\n return undefined;\n case 'sleep':\n for (let i = events.length; i--; ) {\n if (events[i].event.name === 'wait_completed') {\n return events[i].timestamp;\n }\n }\n return undefined;\n case 'run':\n for (let i = events.length; i--; ) {\n const name = events[i].event.name;\n if (\n name === 'run_completed' ||\n name === 'run_failed' ||\n name === 'run_cancelled'\n ) {\n return events[i].timestamp;\n }\n }\n return undefined;\n case 'step':\n for (let i = events.length; i--; ) {\n const name = events[i].event.name;\n if (name === 'step_completed' || name === 'step_failed') {\n return events[i].timestamp;\n }\n if (name === 'step_started' || name === 'step_retrying') {\n return undefined;\n }\n }\n return undefined;\n default:\n return undefined;\n }\n}\n\nexport const SpanNodes = memo(function SpanNodes({\n root,\n scale,\n spans,\n isLive = false,\n scrollSnapshotRef,\n cache,\n customSpanClassNameFunc,\n customSpanEventClassNameFunc,\n}: {\n root: RootNode;\n scale: number;\n spans: VisibleSpan[];\n isLive?: boolean;\n scrollSnapshotRef: MutableRefObject<ScrollSnapshot | undefined>;\n /** Not used in the body — exists solely to bust React.memo when the global memo cache changes. */\n cacheKey?: MemoCacheKey;\n cache: MemoCache;\n customSpanClassNameFunc?: (span: SpanNode) => string;\n customSpanEventClassNameFunc?: (event: VisibleSpanEvent) => string;\n}) {\n return spans.map((x) => (\n <SpanComponent\n cacheKey={cache.get(x.span.spanId)}\n customSpanEventClassNameFunc={customSpanEventClassNameFunc}\n customSpanClassNameFunc={customSpanClassNameFunc}\n key={x.span.spanId}\n node={x}\n root={root}\n scale={scale}\n traceIsLive={isLive}\n scrollSnapshotRef={scrollSnapshotRef}\n />\n ));\n});\n\n// ──────────────────────────────────────────────────────────────────────────\n// Compute inline styles from a SpanLayout\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction getSpanStyle(\n layout: SpanLayout,\n node: VisibleSpan,\n root: RootNode,\n scale: number\n): CSSProperties {\n // Use isExpanded (hovered or selected) for width expansion so that\n // selected small spans stay expanded and show their name.\n const expanded = layout.isExpanded;\n return {\n // Use actualWidth for CSS variable so hover expansion is accurate\n '--span-width': `${Math.max(layout.actualWidth, 1)}px`,\n minWidth: expanded ? layout.width : undefined,\n width: expanded ? undefined : layout.width,\n height: layout.height,\n maxWidth:\n expanded && !layout.isNearRightSide\n ? (root.endTime - node.startTime) * scale\n : undefined,\n containIntrinsicWidth: expanded ? undefined : layout.width,\n containIntrinsicHeight: layout.height,\n left: layout.isNearRightSide ? undefined : layout.left,\n right: layout.isNearRightSide\n ? (root.endTime - node.endTime) * scale\n : undefined,\n top: layout.top,\n } as CSSProperties;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// SpanComponent\n// ──────────────────────────────────────────────────────────────────────────\n\nexport const SpanComponent = memo(function SpanComponent({\n node,\n root,\n scale,\n traceIsLive = false,\n scrollSnapshotRef,\n customSpanClassNameFunc,\n customSpanEventClassNameFunc,\n}: {\n node: VisibleSpan;\n root: RootNode;\n scale: number;\n traceIsLive?: boolean;\n scrollSnapshotRef: MutableRefObject<ScrollSnapshot | undefined>;\n /** Not used in the body — exists solely to bust React.memo for this span. */\n cacheKey?: MemoCacheKey;\n customSpanClassNameFunc?: (span: SpanNode) => string;\n customSpanEventClassNameFunc?: (event: VisibleSpanEvent) => string;\n}): ReactNode {\n const ref = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n node.ref = ref;\n return () => {\n node.ref = undefined;\n };\n }, [node]);\n\n const { span } = node;\n const resourceType = getResourceType(node);\n const [liveNow, setLiveNow] = useState(0);\n\n // Get custom class name from callback if provided\n const customClassName = customSpanClassNameFunc\n ? customSpanClassNameFunc(node)\n : '';\n\n // Workflow span types use colored segments + boundary line markers\n // Generic OTEL spans use diamond event markers\n const isWorkflowSpan = resourceType !== 'default';\n\n // Determine if this span is still active (live). We require the parent run\n // to be explicitly live to avoid completed/cancelled traces continuing to\n // grow due to timing heuristics.\n const data = span.attributes?.data as Record<string, unknown> | undefined;\n const terminalTimestamp = getTerminalTimestamp(resourceType, node);\n const hasTerminalEvent = terminalTimestamp != null;\n const isCompletedByData =\n resourceType === 'hook'\n ? Boolean(data?.disposedAt)\n : Boolean(data?.completedAt);\n const isCompleted = isCompletedByData || hasTerminalEvent;\n const isLive = traceIsLive && isWorkflowSpan && !isCompleted;\n\n useEffect(() => {\n if (!isLive) return;\n setLiveNow(Date.now());\n const interval = setInterval(() => {\n setLiveNow(Date.now());\n }, 250);\n return () => clearInterval(interval);\n }, [isLive]);\n\n const canonicalStartTime = getHighResInMs(span.startTime);\n const canonicalEndTime = getHighResInMs(span.endTime);\n const canonicalDuration = getHighResInMs(span.duration);\n const canonicalActiveStartTime = span.activeStartTime\n ? getHighResInMs(span.activeStartTime)\n : undefined;\n\n const durationMs =\n terminalTimestamp != null\n ? Math.max(0, terminalTimestamp - canonicalStartTime)\n : isLive\n ? Math.max(0, (liveNow || Date.now()) - canonicalStartTime)\n : canonicalDuration;\n const duration = node.isInstrumentationHint\n ? 'Get Started'\n : formatDuration(durationMs);\n const baseNode = {\n ...node,\n startTime: canonicalStartTime,\n endTime: canonicalEndTime,\n duration: canonicalDuration,\n activeStartTime: canonicalActiveStartTime,\n } as VisibleSpan;\n const segmentNode = isLive\n ? ({\n ...baseNode,\n duration: durationMs,\n endTime: canonicalStartTime + durationMs,\n } as VisibleSpan)\n : baseNode;\n const hasSegments =\n isWorkflowSpan &&\n computeSegments(resourceType, segmentNode).segments.length > 0;\n const layout = getSpanLayout(\n resourceType,\n segmentNode,\n root,\n scale,\n scrollSnapshotRef\n );\n\n // For live spans the data-level `node.duration` can be stale (from the last\n // fetch) while the visual width is growing via rAF. Recompute from real\n // elapsed time so that:\n // - height/isSmall classification stays correct (not shrunken to 40%)\n // - React-rendered width matches the rAF-driven width, preventing a brief\n // shrink→expand flash on re-render that breaks cursor hit-testing\n if (isLive) {\n const elapsed = durationMs;\n const liveActualWidth = elapsed * scale;\n const liveWidth = Math.max(liveActualWidth, 4);\n layout.actualWidth = liveActualWidth;\n layout.width = liveWidth;\n layout.isSmall = liveActualWidth < 64;\n layout.isHuge = liveActualWidth >= 500;\n if (!layout.isSmall) {\n layout.height = ROW_HEIGHT;\n layout.top = MARKER_HEIGHT + (ROW_HEIGHT + ROW_PADDING) * segmentNode.row;\n }\n }\n\n // Smoothly grow active span width at 60fps using wall clock time\n useEffect(() => {\n if (!isLive || !ref.current) return;\n\n let rafId = 0;\n const tick = (): void => {\n const $el = ref.current;\n if (!$el) return;\n const elapsed = Date.now() - canonicalStartTime;\n const w = Math.max(elapsed * scale, 2);\n $el.style.width = `${w}px`;\n $el.style.setProperty('--span-width', `${w}px`);\n rafId = requestAnimationFrame(tick);\n };\n rafId = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(rafId);\n }, [isLive, canonicalStartTime, scale]);\n\n const renderNode = segmentNode;\n\n return (\n <>\n <button\n aria-label={`${span.name} - ${duration}`}\n className={clsx(\n styles.spanNode,\n layout.isHuge && styles.huge,\n layout.isSmall && styles.small,\n layout.isExpanded && styles.xHover,\n node.isHighlighted\n ? styles.colorHighlight\n : getSpanColorClassName(node),\n node.isHighlighted === false && styles.unlit,\n customClassName,\n hasSegments && styles.hasSegments\n )}\n data-span-id={span.spanId}\n data-start-time={segmentNode.startTime - root.startTime}\n data-right-side={layout.isNearRightSide}\n data-selected={node.isSelected ? '' : undefined}\n ref={ref}\n style={getSpanStyle(layout, segmentNode, root, scale)}\n type=\"button\"\n >\n <SpanContent\n durationMs={durationMs}\n resourceType={resourceType}\n node={renderNode}\n layout={layout}\n />\n </button>\n {segmentNode.events && !layout.isSmall\n ? segmentNode.events.map((x) => (\n <SpanEventComponent\n customSpanEventClassNameFunc={customSpanEventClassNameFunc}\n event={x}\n key={x.key}\n node={segmentNode}\n root={root}\n scale={scale}\n asBoundary={isWorkflowSpan}\n />\n ))\n : null}\n </>\n );\n});\n\n// ──────────────────────────────────────────────────────────────────────────\n// SpanEventComponent\n// ──────────────────────────────────────────────────────────────────────────\n\n/** Human-readable labels for workflow event types */\nconst BOUNDARY_LABELS: Record<string, string> = {\n step_started: 'Started',\n step_retrying: 'Retrying',\n step_failed: 'Failed',\n hook_created: 'Created',\n hook_received: 'Received',\n hook_disposed: 'Resolved',\n wait_created: 'Sleep started',\n wait_completed: 'Sleep completed',\n run_started: 'Started',\n run_completed: 'Completed',\n run_failed: 'Run failed',\n step_completed: 'Completed',\n};\n\nexport const SpanEventComponent = memo(function SpanEventComponent({\n event,\n node,\n root,\n scale,\n customSpanEventClassNameFunc,\n asBoundary = false,\n}: {\n event: VisibleSpanEvent;\n node: VisibleSpan;\n root: RootNode;\n scale: number;\n customSpanEventClassNameFunc?: (event: VisibleSpanEvent) => string;\n asBoundary?: boolean;\n}): ReactNode {\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n event.ref = ref;\n return () => {\n event.ref = undefined;\n };\n }, [event]);\n\n const {\n event: { name },\n } = event;\n const timestamp = formatDuration(event.timestamp - root.startTime);\n const displayLabel = asBoundary ? (BOUNDARY_LABELS[name] ?? name) : name;\n\n // For boundary events, compute the duration of the phase.\n // \"Forward\" events (started, retrying) measure until the next event.\n // \"Terminal\" events (completed) measure from the previous started event.\n const isForwardEvent =\n asBoundary &&\n (name === 'step_started' ||\n name === 'run_started' ||\n name === 'step_retrying');\n const isTerminalEvent =\n asBoundary && (name === 'step_completed' || name === 'run_completed');\n\n let phaseDuration: string | null = null;\n let phaseLabel: string | null = null;\n if ((isForwardEvent || isTerminalEvent) && node.events) {\n const sortedNodeEvents = [...node.events].sort(\n (a, b) => a.timestamp - b.timestamp\n );\n const currentIdx = sortedNodeEvents.findIndex((e) => e.key === event.key);\n\n if (isTerminalEvent) {\n // Look backward to find the last step_started\n let prevStartTime: number | null = null;\n for (let i = currentIdx - 1; i >= 0; i--) {\n if (sortedNodeEvents[i].event.name === 'step_started') {\n prevStartTime = sortedNodeEvents[i].timestamp;\n break;\n }\n }\n if (prevStartTime !== null) {\n phaseDuration = formatDuration(event.timestamp - prevStartTime);\n phaseLabel = 'Executed';\n }\n } else {\n // Look forward to the next event\n const nextEvent = sortedNodeEvents[currentIdx + 1];\n const endTime = nextEvent ? nextEvent.timestamp : node.endTime;\n phaseDuration = formatDuration(endTime - event.timestamp);\n phaseLabel = name === 'step_retrying' ? 'Waited' : 'Executed';\n }\n }\n\n const left = (event.timestamp - root.startTime) * scale;\n const top = MARKER_HEIGHT + (ROW_HEIGHT + ROW_PADDING) * node.row;\n const isLeftAligned =\n node.duration <= 0 ||\n (event.timestamp - node.startTime) / node.duration < 0.5;\n\n // Get custom class name from callback if provided\n const customClassName = customSpanEventClassNameFunc\n ? customSpanEventClassNameFunc(event)\n : '';\n\n return (\n <div\n title={\n phaseDuration\n ? `${displayLabel} ${timestamp}\\n${phaseLabel} ${phaseDuration}`\n : `${displayLabel} ${timestamp}`\n }\n className={clsx(\n styles.spanNodeEvent,\n customClassName,\n asBoundary && styles.boundaryMarker,\n node.isHighlighted\n ? styles.colorHighlight\n : getSpanColorClassName(node),\n node.isHighlighted === false && styles.unlit\n )}\n data-hovered={event.isHovered}\n ref={ref}\n style={\n {\n left,\n top,\n } as CSSProperties\n }\n >\n <div\n className={clsx(\n styles.hoverInfo,\n isLeftAligned ? styles.alignStart : styles.alignEnd\n )}\n >\n {asBoundary ? (\n <>\n <span className={styles.eventName}>{displayLabel}</span>\n <span className={styles.eventTimestamp}>{timestamp}</span>\n {phaseDuration ? (\n <>\n <span className={styles.eventName}>{phaseLabel}</span>\n <span className={styles.eventTimestamp}>{phaseDuration}</span>\n </>\n ) : null}\n </>\n ) : (\n <>\n <span className={styles.eventName}>{name}</span>\n <span className={styles.eventTimestamp}>{timestamp}</span>\n </>\n )}\n </div>\n {asBoundary ? (\n <div className={styles.boundaryLine} />\n ) : (\n <div className={styles.eventDiamond} />\n )}\n </div>\n );\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"search-input.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/search-input.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,MAAM,4BAA4B,CAAC;AAEhD,MAAM,UAAU,WAAW,CAAC,EAC1B,MAAM,EACN,KAAK,EACL,KAAK,EACL,WAAW,EACX,QAAQ,GAOT;IACC,OAAO,CACL,iBAAO,SAAS,EAAE,MAAM,CAAC,gBAAgB,aACvC,cAAK,SAAS,EAAE,MAAM,CAAC,iBAAiB,YACtC,KAAC,mBAAmB,KAAG,GACnB,EACN,gBACE,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,KAAK,EACZ,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GACxB,IACI,CACT,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO,CACL,eACE,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,iBACC,MAAM,EAClB,SAAS,EAAC,OAAO,aAEjB,iBAAQ,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,EAAC,CAAC,EAAC,KAAK,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,KAAK,GAAG,EACxE,eACE,CAAC,EAAC,kBAAkB,EACpB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,KAAK,EACjB,aAAa,EAAC,OAAO,GACrB,IACE,CACP,CAAC;AACJ,CAAC","sourcesContent":["import type { ChangeEventHandler, ReactNode } from 'react';\nimport styles from '../trace-viewer.module.css';\n\nexport function SearchInput({\n height,\n width,\n value,\n placeholder,\n onChange,\n}: {\n height: number | string;\n width?: number | string;\n value: string;\n placeholder?: string;\n onChange: ChangeEventHandler<HTMLInputElement>;\n}): ReactNode {\n return (\n <label className={styles.searchInputLabel}>\n <div className={styles.searchInputPrefix}>\n <MagnifyingGlassIcon />\n </div>\n <input\n type=\"search\"\n value={value}\n placeholder={placeholder}\n onChange={onChange}\n style={{ height, width }}\n />\n </label>\n );\n}\n\nfunction MagnifyingGlassIcon(): ReactNode {\n return (\n <svg\n width={16}\n height={16}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle cx=\"7\" cy=\"7\" r=\"4.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path\n d=\"M11.5 11.5L14 14\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/search.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAkB,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,MAAM,MAAM,4BAA4B,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,UAAU,SAAS;IACvB,OAAO,CACL,cAAK,SAAS,EAAE,MAAM,CAAC,SAAS,YAC9B,KAAC,kBAAkB,KAAG,GAClB,CACP,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,EAAE,CAAC;IACtC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,UAAU,CACxB,GAAG,EAAE,CACH,QAAQ,CAAC;YACP,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,KAAK;SACd,CAAC,EACJ,GAAG,CACJ,CAAC;QAEF,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAEtB,OAAO,CACL,cAAK,SAAS,EAAE,MAAM,CAAC,WAAW,YAChC,KAAC,WAAW,IACV,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,WAAW,EAAC,oBAAe,EAC3B,KAAK,EAAE,KAAK,EACZ,KAAK,EAAC,MAAM,GACZ,GACE,CACP,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\nimport { type ReactNode, useEffect, useState } from 'react';\nimport { useTraceViewer } from '../context';\nimport styles from '../trace-viewer.module.css';\nimport { SEARCH_HEIGHT } from '../util/constants';\nimport { SearchInput } from './search-input';\n\nexport function SearchBar(): ReactNode {\n return (\n <nav className={styles.searchBar}>\n <SearchInputWrapper />\n </nav>\n );\n}\n\nfunction SearchInputWrapper(): ReactNode {\n const { dispatch } = useTraceViewer();\n const [value, setValue] = useState('');\n\n useEffect(() => {\n const timeout = setTimeout(\n () =>\n dispatch({\n type: 'setFilter',\n filter: value,\n }),\n 100\n );\n\n return () => {\n clearTimeout(timeout);\n };\n }, [dispatch, value]);\n\n return (\n <div className={styles.searchInput}>\n <SearchInput\n height={SEARCH_HEIGHT}\n onChange={(e) => setValue(e.target.value)}\n placeholder=\"Search spans…\"\n value={value}\n width=\"100%\"\n />\n </div>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"span-content.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/span-content.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport type { CSSProperties, ReactNode } from 'react';\nimport styles from '../trace-viewer.module.css';\nimport type { SpanNode } from '../types';\nimport { formatDuration } from '../util/timing';\nimport {\n type Segment,\n type SegmentStatus,\n SEGMENT_CLASS_MAP,\n computeSegments,\n} from './span-segments';\nimport type { ResourceType, SpanLayout } from './span-strategies';\n\n// ──────────────────────────────────────────────────────────────────────────\n// Shared helpers\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction getDuration(node: SpanNode): string {\n if (node.isInstrumentationHint) {\n return 'Get Started';\n }\n return formatDuration(node.duration);\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Segment rendering (shared across all workflow span types)\n// ──────────────────────────────────────────────────────────────────────────\n\nconst SEGMENT_LABELS: Record<SegmentStatus, string> = {\n queued: 'Queued',\n running: '',\n failed: 'Failed',\n retrying: 'Retry wait',\n succeeded: 'Executed',\n waiting: 'Waiting',\n sleeping: 'Sleeping',\n received: 'Received',\n};\n\nfunction SegmentLayer({\n segments,\n spanDuration,\n}: {\n segments: Segment[];\n spanDuration: number;\n}): ReactNode {\n if (segments.length === 0) return null;\n\n return (\n <div className={styles.segmentLayer}>\n {segments.map((seg, i) => {\n const className =\n styles[SEGMENT_CLASS_MAP[seg.status] as keyof typeof styles];\n const segDuration =\n (seg.endFraction - seg.startFraction) * spanDuration;\n const label = SEGMENT_LABELS[seg.status];\n const style: CSSProperties = {\n left: `${seg.startFraction * 100}%`,\n width: `${(seg.endFraction - seg.startFraction) * 100}%`,\n };\n\n return (\n <div\n key={`seg-${seg.status}-${String(i)}`}\n className={`${styles.segment} ${String(className)}`}\n style={style}\n title={\n label\n ? `${label} ${formatDuration(segDuration)}`\n : formatDuration(segDuration)\n }\n />\n );\n })}\n </div>\n );\n}\n\n/** Build inline segment tags to render next to the span name. */\nfunction getSegmentTags(\n segments: Segment[],\n spanDuration: number\n): { label: string; duration: string }[] {\n const tags: { label: string; duration: string }[] = [];\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n const label = SEGMENT_LABELS[seg.status];\n if (!label) continue; // skip \"running\" which has no label\n let segDuration = (seg.endFraction - seg.startFraction) * spanDuration;\n\n // For terminal segments (succeeded/failed) with ~0 duration,\n // use the preceding running segment's duration instead.\n if (\n segDuration < 1 &&\n (seg.status === 'succeeded' || seg.status === 'failed') &&\n i > 0\n ) {\n const prev = segments[i - 1];\n if (prev.status === 'running') {\n segDuration = (prev.endFraction - prev.startFraction) * spanDuration;\n }\n }\n\n // Skip tags that still have no meaningful duration\n if (segDuration < 1) continue;\n\n tags.push({ label, duration: formatDuration(segDuration) });\n }\n return tags;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Text content (shared label + duration rendering)\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction TextContent({\n node,\n layout,\n durationMs,\n segmentTags,\n}: SpanContentProps & {\n segmentTags?: { label: string; duration: string }[];\n}): ReactNode {\n const duration = node.isInstrumentationHint\n ? getDuration(node)\n : formatDuration(durationMs ?? node.duration);\n\n if (layout.isSmall && !layout.isHovered) {\n return null;\n }\n\n const showTags =\n segmentTags &&\n segmentTags.length > 0 &&\n (layout.isHovered || layout.width > 200);\n\n return (\n <>\n <span className={styles.spanName}>\n {node.label || node.span.name}\n {showTags\n ? segmentTags.map((tag, i) => (\n <span key={i} className={styles.segmentTag}>\n {' · '}\n {tag.label} {tag.duration}\n </span>\n ))\n : null}\n </span>\n {layout.isHuge ? <span className={styles.spanSpacer} /> : null}\n {layout.isHovered || layout.width > 128 ? (\n <span className={styles.spanDuration}>{duration}</span>\n ) : null}\n </>\n );\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Content props\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface SpanContentProps {\n node: SpanNode;\n layout: SpanLayout;\n durationMs?: number;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Default content (generic OTEL spans — no segments)\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction DefaultContent({ node, layout }: SpanContentProps): ReactNode {\n return <TextContent node={node} layout={layout} />;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Workflow content (segments + text for workflow span types)\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction WorkflowContent({\n resourceType,\n node,\n layout,\n durationMs,\n}: SpanContentProps & { resourceType: ResourceType }): ReactNode {\n const spanDuration = durationMs ?? node.duration;\n const { segments } = computeSegments(resourceType, node);\n const segmentTags = getSegmentTags(segments, spanDuration);\n\n return (\n <>\n <SegmentLayer segments={segments} spanDuration={spanDuration} />\n <TextContent\n durationMs={spanDuration}\n node={node}\n layout={layout}\n segmentTags={segmentTags}\n />\n </>\n );\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Per-type content components\n// ──────────────────────────────────────────────────────────────────────────\n\nexport function RunContent(props: SpanContentProps): ReactNode {\n return <WorkflowContent resourceType=\"run\" {...props} />;\n}\n\nexport function StepContent(props: SpanContentProps): ReactNode {\n return <WorkflowContent resourceType=\"step\" {...props} />;\n}\n\nexport function HookContent(props: SpanContentProps): ReactNode {\n return <WorkflowContent resourceType=\"hook\" {...props} />;\n}\n\nexport function SleepContent(props: SpanContentProps): ReactNode {\n return <WorkflowContent resourceType=\"sleep\" {...props} />;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Dispatcher\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Returns the inner content for a span based on its resource type.\n */\nexport function SpanContent({\n resourceType,\n ...props\n}: SpanContentProps & { resourceType: ResourceType }): ReactNode {\n switch (resourceType) {\n case 'run':\n return <RunContent {...props} />;\n case 'step':\n return <StepContent {...props} />;\n case 'hook':\n return <HookContent {...props} />;\n case 'sleep':\n return <SleepContent {...props} />;\n default:\n return <DefaultContent {...props} />;\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"span-detail-panel.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/span-detail-panel.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { clsx } from 'clsx';\nimport type { PointerEventHandler, ReactNode } from 'react';\nimport {\n Fragment,\n memo,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n initialState,\n useCustomPanelComponent,\n useTraceViewer,\n} from '../context';\nimport styles from '../trace-viewer.module.css';\nimport type {\n GetQuickLinks,\n QuickLinkValue,\n RootNode,\n Span,\n SpanNode,\n TraceNode,\n} from '../types';\nimport { formatDuration } from '../util/timing';\nimport { getSpanColorClassName } from './node';\nimport {\n ButtonLink,\n IconChevronDown,\n IconCross,\n IconExternalSmall,\n Link,\n Note,\n Skeleton,\n} from './ui';\n\nconst percentage = (n: number): string => `${(100 * n).toFixed(3)}%`;\n\ninterface GroupedAttribute {\n prefix: string;\n attributes: Attribute[];\n}\n\ninterface Attribute {\n suffix: string;\n key: string;\n value: string;\n}\n\nconst sortWord = (a: string, b: string): number => {\n if (a < b) {\n return -1;\n } else if (a > b) {\n return 1;\n }\n return 0;\n};\n\nconst getGroupedAttributes = (\n attributes: Span['attributes']\n): GroupedAttribute[] => {\n // Build groups of items with the same prefix\n const groups: Record<string, GroupedAttribute> = {};\n for (const [key, value] of Object.entries(attributes)) {\n const dotIndex = key.indexOf('.');\n let prefix = '';\n let suffix = '';\n if (dotIndex !== -1) {\n prefix = key.substring(0, dotIndex);\n suffix = key.substring(dotIndex + 1);\n } else {\n suffix = key;\n }\n\n let group = groups[prefix];\n if (!group) {\n group = {\n prefix,\n attributes: [],\n };\n groups[prefix] = group;\n }\n group.attributes.push({\n key,\n suffix,\n value: String(value),\n });\n }\n\n // List and sort everything\n const result = Array.from(Object.values(groups)).sort((a, b) =>\n sortWord(a.prefix, b.prefix)\n );\n for (const group of result) {\n group.attributes.sort((a, b) => sortWord(a.suffix, b.suffix));\n }\n return result;\n};\n\n// biome-ignore lint/correctness/noUnusedFunctionParameters: ignored using `--suppress`\nconst getAncestors = (_root: RootNode, start: SpanNode | null): SpanNode[] => {\n const result: SpanNode[] = [];\n\n if (!start) return result;\n\n for (let node: TraceNode = start; 'parent' in node; node = node.parent) {\n result.unshift(node);\n }\n\n return result;\n};\n\nexport const SpanDetailPanelBody = () => {\n const {\n state: { root, selected, resourceMap, getQuickLinks },\n dispatch,\n } = useTraceViewer();\n\n const ancestors = useMemo(\n () => getAncestors(root, selected),\n [root, selected]\n );\n\n const attributeGroups = useMemo(\n () => getGroupedAttributes(selected?.span.attributes ?? {}),\n [selected]\n );\n\n const resourceAttributeGroups = useMemo(() => {\n const resourceName = selected?.span.resource;\n if (!resourceName) return [];\n const resourceAttributes = resourceMap[resourceName];\n if (!resourceAttributes) return [];\n return getGroupedAttributes(resourceAttributes);\n }, [resourceMap, selected]);\n\n if (!selected) return null;\n\n const { span } = selected;\n\n const isEntrySpan = detectIsEntrySpan(selected);\n\n return (\n <>\n {selected.isVercel ? <InfraSpanDescription node={selected} /> : null}\n {selected.isInstrumentationHint ? <InstrumentationHint /> : null}\n {!selected.isInstrumentationHint && ancestors.length ? (\n <DetailGroup className={styles.ancestorGroup} name=\"Location\">\n {ancestors.map((node) => (\n <button\n className={styles.ancestorNode}\n key={`${selected.span.spanId}.${node.span.spanId}`}\n onClick={() =>\n dispatch({\n type: 'select',\n id: node.span.spanId,\n })\n }\n type=\"button\"\n >\n <div className={styles.ancestorText}>\n <span className={styles.ancestorName}>\n {node.label || node.span.name}\n </span>\n <span className={styles.ancestorDuration}>\n {formatDuration(node.duration)}\n </span>\n </div>\n <span aria-hidden className={styles.ancestorLineContainer}>\n <span\n className={clsx(\n styles.ancestorLine,\n getSpanColorClassName(node)\n )}\n style={{\n left: percentage(\n (node.startTime - root.startTime) / root.duration\n ),\n width: percentage(node.duration / root.duration),\n }}\n />\n </span>\n </button>\n ))}\n </DetailGroup>\n ) : null}\n {isEntrySpan ? (\n <EntrySpanLinks getQuickLinks={getQuickLinks} span={selected.span} />\n ) : null}\n {selected.events?.length ? (\n <DetailGroup name=\"Events\">\n {selected.events.map((event) => (\n <Fragment key={event.key}>\n <dl className={styles.spanDetailPanelAttribute}>\n <dt className={styles.spanDetailPanelAttributeKey}>\n {event.event.name}\n </dt>\n <dd className={styles.spanDetailPanelAttributeValue}>\n {formatDuration(event.timestamp - root.startTime)}\n </dd>\n </dl>\n {Object.entries(event.event.attributes).map(([key, value]) => (\n <DetailLine\n key={key}\n name={`${event.event.name}.${key}`}\n value={value}\n />\n ))}\n </Fragment>\n ))}\n </DetailGroup>\n ) : null}\n {attributeGroups.length ? (\n <DetailGroup name=\"Attributes\">\n {attributeGroups.map((group) => (\n <Fragment key={group.prefix}>\n {group.attributes.map(({ key, value }) => (\n <DetailLine key={key} name={key} value={value} />\n ))}\n </Fragment>\n ))}\n </DetailGroup>\n ) : null}\n {resourceAttributeGroups.length ? (\n <DetailGroup name=\"Resource\">\n {resourceAttributeGroups.map((group) => (\n <Fragment key={group.prefix}>\n {group.attributes.map(({ key, value }) => (\n <DetailLine key={key} name={key} value={value} />\n ))}\n </Fragment>\n ))}\n </DetailGroup>\n ) : null}\n {selected.isInstrumentationHint ? null : (\n <DetailGroup name=\"Library\">\n <DetailLine name=\"name\" value={span.library.name} />\n {span.library.version ? (\n <DetailLine name=\"version\" value={span.library.version} />\n ) : null}\n </DetailGroup>\n )}\n </>\n );\n};\n\nexport function SpanDetailPanel({\n attached = false,\n}: {\n attached?: boolean;\n}): ReactNode {\n const {\n state: { selected, isMobile },\n dispatch,\n } = useTraceViewer();\n const customPanelComponent = useCustomPanelComponent();\n\n if (!selected) return null;\n\n const { span } = selected;\n\n return (\n <div className={clsx(styles.spanDetailPanel, isMobile && styles.mobile)}>\n {attached && !isMobile ? <PanelResizer /> : null}\n <div className={styles.spanDetailPanelTop}>\n <div className={styles.spanDetailPanelTopInfo}>\n {/* Name/ID first */}\n <span className={styles.spanDetailPanelName} title={span.name}>\n {span.name}\n </span>\n {/* Right side: duration badge, separator, close */}\n <div className={styles.spanDetailPanelCorner}>\n {selected.isInstrumentationHint ? null : (\n <span className={styles.spanDetailPanelDuration}>\n {formatDuration(selected.duration)}\n </span>\n )}\n <div className={styles.spanDetailPanelCloseVerticalRule} />\n <button\n aria-label=\"Close Span Details\"\n className={styles.spanDetailPanelClose}\n onClick={() =>\n dispatch({\n type: 'deselect',\n })\n }\n type=\"button\"\n >\n <IconCross color=\"gray-700\" size={20} />\n </button>\n </div>\n </div>\n </div>\n <div className={clsx('flex gap-3', styles.spanDetailPanelBody)}>\n {customPanelComponent || <SpanDetailPanelBody />}\n </div>\n </div>\n );\n}\n\nconst EXPANDED_STORAGE_KEY_PREFIX = 'vc-trace-span-exp:';\n\nfunction DetailGroup({\n name,\n className = '',\n children,\n}: {\n name: string;\n className?: string;\n children: ReactNode;\n}): ReactNode {\n const [isExpanded, setIsExpanded] = useState(() => {\n if (!('localStorage' in globalThis)) return true;\n return (\n localStorage.getItem(`${EXPANDED_STORAGE_KEY_PREFIX}${name}`) !== '0'\n );\n });\n\n const toggleExpanded = useCallback(() => {\n setIsExpanded((x) => {\n const willBeExpanded = !x;\n localStorage.setItem(\n `${EXPANDED_STORAGE_KEY_PREFIX}${name}`,\n String(Number(willBeExpanded))\n );\n return willBeExpanded;\n });\n }, [name]);\n\n return (\n <div\n className={clsx(\n styles.detailGroup,\n isExpanded ? styles.expanded : styles.collapsed,\n className\n )}\n >\n <button\n className={styles.detailHeading}\n onClick={toggleExpanded}\n type=\"button\"\n >\n <span>{name}</span>\n <IconChevronDown />\n </button>\n {isExpanded ? children : null}\n </div>\n );\n}\n\nconst CommonHttpVerbs = new Set([\n 'OPTIONS',\n 'HEAD',\n 'GET',\n 'PUT',\n 'POST',\n 'DELETE',\n]);\nconst KnownSpans: Record<string, string> = {\n 'Resolve Deployment': `How long it took Vercel's routing layer to retrieve details for the deployment.`,\n 'Resolve Cache': `How long it took Vercel's routing layer to check for a cached function invocation.`,\n 'Resolve Route': `How long it took Vercel's routing layer to resolve routing rules, including redirects and rewrites.`,\n 'Invoke Middleware': `How long it took this middleware to start and run user code.`,\n 'Invoke Function': `How long it took this Vercel Function to start and run user code.`,\n waitUntil: `How long it took to run user code inside of waitUntil.`,\n 'Start VM': `How long it took to start the Virtual Machine which contains the Vercel Function.`,\n 'Spawn Node.js': `How long it took the Virtual Machine to start the Node.js runtime.`,\n 'Spawn Python': `How long it took the Virtual Machine to start the Python runtime.`,\n 'Init User Code': `How long it took to import the user code and run any globally-scoped code.`,\n};\n\nconst ColdStartSpanNames = new Set([\n 'Start VM',\n 'Spawn Node.js',\n 'Spawn Python',\n 'Init User Code',\n]);\n\nconst getRegion = (\n node: SpanNode | RootNode | null | undefined\n): string | null => {\n if (!node || !('span' in node)) {\n return null;\n }\n\n const attr = node.span.attributes;\n const region = attr['vercel.region'] || attr['vercel.function.region'];\n if (region) return String(region);\n return null;\n};\n\nconst getNote = (node: SpanNode): ReactNode => {\n const { name } = node.span;\n const region = getRegion(node);\n const parentRegion = getRegion(node.parent);\n\n if (node.span.attributes['vercel.middleware.internal'] === 'true') {\n return 'The Vercel Toolbar created this middleware.';\n } else if (\n ColdStartSpanNames.has(name) ||\n (name === 'Invoke Function' &&\n node.children.some((x) => ColdStartSpanNames.has(x.span.name)))\n ) {\n return 'This function encountered a cold start.';\n } else if (region && parentRegion && region !== parentRegion) {\n return 'This request was routed across regions.';\n }\n\n return null;\n};\n\nconst detectIsEntrySpan = (node: SpanNode): boolean => {\n if (!node.isVercel) return false;\n const { name } = node.span;\n const spaceIndex = name.indexOf(' ');\n if (spaceIndex === -1) return false;\n const firstWord = name.substring(0, spaceIndex);\n return CommonHttpVerbs.has(firstWord);\n};\n\nfunction InfraSpanDescription({ node }: { node: SpanNode }): ReactNode {\n const { name } = node.span;\n let description = KnownSpans[name];\n\n if (!description && detectIsEntrySpan(node)) {\n description = `How long it took for Vercel to process the request and send the response.`;\n }\n\n if (!description) return null;\n\n const note = getNote(node);\n\n return (\n <DetailGroup name=\"What is this?\">\n <div className={styles.infraSpanDescription}>\n <span>{description}</span>\n {note ? <Note>{note}</Note> : note}\n </div>\n </DetailGroup>\n );\n}\n\nconst EntrySpanLinks = memo(function EntrySpanLinks({\n getQuickLinks,\n span,\n}: {\n getQuickLinks: GetQuickLinks;\n span: Span;\n}): ReactNode {\n const links = getQuickLinks(span);\n\n if (!links.length) return null;\n\n return (\n <DetailGroup name=\"Links\">\n {links.map(({ key, value }) => (\n <EntrySpanLink key={key} link={value} name={key} />\n ))}\n </DetailGroup>\n );\n});\n\ninterface ResolvablePromise<T> extends Promise<T> {\n __resolvedValue?: T;\n __rejectedValue?: unknown;\n}\n\nfunction usePromise<T>(promise: ResolvablePromise<T>): T | undefined {\n const [_, setLatest] = useState({});\n const fulfilled =\n promise.__resolvedValue !== undefined ||\n promise.__rejectedValue !== undefined;\n useEffect(() => {\n if (fulfilled) return;\n\n promise\n .then((value) => {\n promise.__resolvedValue = value;\n })\n .catch((err) => {\n promise.__rejectedValue = err;\n })\n .finally(() => setLatest({}));\n }, [promise, fulfilled]);\n\n return promise.__resolvedValue;\n}\n\nfunction EntrySpanLink({\n name,\n link: linkPromise,\n}: {\n name: string;\n link: Promise<QuickLinkValue>;\n}): ReactNode {\n const link = usePromise(linkPromise);\n\n return (\n <Link\n as={link ? undefined : 'span'}\n className={clsx(\n styles.spanDetailPanelAttribute,\n styles.spanDetailPanelQuickLink\n )}\n href={link?.href || ''}\n >\n <span className={styles.spanDetailPanelAttributeKey}>{name}</span>\n <span\n className={clsx(\n styles.spanDetailPanelAttributeValue,\n styles.spanDetailPanelQuickLinkLabel\n )}\n >\n {link ? (\n <>\n {link.label}\n {link.icon || <IconExternalSmall color=\"gray-900\" />}\n </>\n ) : (\n <>\n <Skeleton height={18} width={32 + name.length * 8} />\n <Skeleton height={18} rounded width={18} />\n </>\n )}\n </span>\n </Link>\n );\n}\n\nfunction InstrumentationHint(): ReactNode {\n return (\n <DetailGroup name=\"What is this?\">\n <div className={styles.infraSpanDescription}>\n <span>{`You can visualize your application's spans alongside Vercel's spans in this viewer.`}</span>\n <ButtonLink\n href=\"https://vercel.com/docs/session-tracing#adding-custom-spans\"\n size=\"small\"\n target=\"_blank\"\n >\n Get Started\n </ButtonLink>\n </div>\n </DetailGroup>\n );\n}\n\nfunction DetailLine({\n name,\n value,\n}: {\n name: string;\n value: unknown;\n}): ReactNode {\n return (\n <dl className={styles.spanDetailPanelAttribute}>\n <dt className={styles.spanDetailPanelAttributeKey}>{name}</dt>\n <dd\n className={styles.spanDetailPanelAttributeValue}\n title={String(value)}\n >\n {String(value)}\n </dd>\n </dl>\n );\n}\n\ninterface ResizeGestureRef {\n start: {\n x: number;\n width: number;\n };\n x: number;\n width: number;\n isHeld: boolean;\n}\n\n/**\n * Resizer component for the trace viewer panel.\n */\nexport function PanelResizer(): ReactNode {\n const {\n state: { panelWidth },\n dispatch,\n } = useTraceViewer();\n const gestureRef = useRef<ResizeGestureRef>({\n start: {\n x: 0,\n width: panelWidth,\n },\n x: 0,\n width: panelWidth,\n isHeld: false,\n });\n gestureRef.current.width = panelWidth;\n\n const onPointerDown = useCallback<PointerEventHandler>((event) => {\n if (event.pointerType !== 'mouse') return;\n event.preventDefault();\n const g = gestureRef.current;\n g.start.x = event.clientX;\n g.x = event.clientX;\n g.start.width = g.width;\n g.isHeld = true;\n }, []);\n\n const onDoubleClick = useCallback(() => {\n dispatch({\n type: 'setPanelWidth',\n width: initialState.panelWidth,\n });\n }, [dispatch]);\n\n useEffect(() => {\n let nextFrame = 0;\n const onFrame = (): void => {\n const g = gestureRef.current;\n const width = g.start.width + g.start.x - g.x;\n dispatch({\n type: 'setPanelWidth',\n width,\n });\n };\n\n const onPointerMove = (event: PointerEvent): void => {\n if (!gestureRef.current.isHeld) return;\n event.preventDefault();\n gestureRef.current.x = event.clientX;\n cancelAnimationFrame(nextFrame);\n nextFrame = requestAnimationFrame(onFrame);\n };\n const onPointerUp = (): void => {\n gestureRef.current.isHeld = false;\n };\n\n window.addEventListener('pointermove', onPointerMove);\n window.addEventListener('pointerup', onPointerUp);\n\n return () => {\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', onPointerUp);\n };\n }, [dispatch]);\n\n return (\n <div\n aria-hidden\n className={styles.spanDetailPanelResizer}\n onDoubleClick={onDoubleClick}\n onPointerDown={onPointerDown}\n />\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"span-segments.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/span-segments.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SpanNode, SpanNodeEvent } from '../types';\nimport type { ResourceType } from './span-strategies';\n\n// ──────────────────────────────────────────────────────────────────────────\n// Segment types\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Visual status of a segment within a span bar.\n *\n * - queued: Waiting to start (hatched pattern)\n * - running: Actively executing (solid blue)\n * - failed: Attempt that ended in failure (soft red)\n * - retrying: Waiting between retry attempts (hatched pattern)\n * - succeeded: Final successful attempt (soft green)\n * - waiting: Passive waiting, e.g. hook waiting for payload (hatched pattern)\n * - sleeping: Sleep in progress (soft amber)\n * - received: Hook received a payload (soft blue)\n */\nexport type SegmentStatus =\n | 'queued'\n | 'running'\n | 'failed'\n | 'retrying'\n | 'succeeded'\n | 'waiting'\n | 'sleeping'\n | 'received';\n\nexport interface Segment {\n /** Fraction of span width where this segment starts (0–1) */\n startFraction: number;\n /** Fraction of span width where this segment ends (0–1) */\n endFraction: number;\n /** Visual status controlling color/pattern */\n status: SegmentStatus;\n}\n\n/**\n * A boundary between two segments, representing an event that caused\n * a transition. Rendered as a hoverable divider with a tooltip.\n */\nexport interface SegmentBoundary {\n /** Fractional position along the span (0–1) */\n fraction: number;\n /** Display label for the tooltip (e.g. \"step_started\") */\n label: string;\n /** Formatted timestamp relative to span start */\n offsetMs: number;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// CSS class mapping (segment status → module CSS class name)\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Maps a SegmentStatus to the CSS module class name to use.\n * These class names must exist in trace-viewer.module.css.\n */\nexport const SEGMENT_CLASS_MAP: Record<SegmentStatus, string> = {\n queued: 'segQueued',\n running: 'segRunning',\n failed: 'segFailed',\n retrying: 'segRetrying',\n succeeded: 'segSucceeded',\n waiting: 'segWaiting',\n sleeping: 'segSleeping',\n received: 'segReceived',\n};\n\n// ──────────────────────────────────────────────────────────────────────────\n// Helpers\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction clampFraction(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nfunction timeToFraction(\n time: number,\n spanStart: number,\n spanDuration: number\n): number {\n if (spanDuration <= 0) return 0;\n return clampFraction((time - spanStart) / spanDuration);\n}\n\n/**\n * Sort events by timestamp ascending.\n */\nfunction sortedEvents(events: SpanNodeEvent[]): SpanNodeEvent[] {\n return [...events].sort((a, b) => a.timestamp - b.timestamp);\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Step segments\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Compute segments for a step span.\n *\n * Timeline: [queued] → [attempt₁ (fail)] → [retry wait] → [attempt₂ (fail)] → ... → [attemptₙ (success)]\n *\n * Events used: step_started, step_retrying, step_failed, step_completed\n * The final segment is 'succeeded' if no trailing step_retrying/step_failed.\n */\nfunction computeStepSegments(node: SpanNode): Segment[] {\n const events = node.events ? sortedEvents(node.events) : [];\n const { startTime, duration } = node;\n const segments: Segment[] = [];\n\n if (duration <= 0) return segments;\n\n // Build a timeline of event boundaries\n interface EventMark {\n time: number;\n type: string;\n }\n const marks: EventMark[] = events\n .filter((e) =>\n [\n 'step_started',\n 'step_retrying',\n 'step_failed',\n 'step_completed',\n ].includes(e.event.name)\n )\n .map((e) => ({ time: e.timestamp, type: e.event.name }));\n\n if (marks.length === 0) {\n // No events — show entire span as running\n segments.push({ startFraction: 0, endFraction: 1, status: 'running' });\n return segments;\n }\n\n // Queued period: from span start to first event\n const firstMark = marks[0];\n const firstFraction = timeToFraction(firstMark.time, startTime, duration);\n if (firstFraction > 0.001) {\n segments.push({\n startFraction: 0,\n endFraction: firstFraction,\n status: 'queued',\n });\n }\n\n // Walk through events to build attempt/retry segments\n for (let i = 0; i < marks.length; i++) {\n const mark = marks[i];\n const markFraction = timeToFraction(mark.time, startTime, duration);\n const nextMark = marks[i + 1];\n const nextFraction = nextMark\n ? timeToFraction(nextMark.time, startTime, duration)\n : 1;\n\n if (mark.type === 'step_started') {\n // This is the start of an execution attempt.\n // It runs until the next event (step_retrying or step_failed) or end of span.\n const isLastMark = i === marks.length - 1;\n if (isLastMark) {\n // Last event is step_started — this attempt is either still running or succeeded\n segments.push({\n startFraction: markFraction,\n endFraction: 1,\n status: 'succeeded',\n });\n } else {\n // Attempt runs until the next event\n const nextType = nextMark.type;\n const attemptStatus: SegmentStatus =\n nextType === 'step_retrying' || nextType === 'step_failed'\n ? 'failed'\n : nextType === 'step_completed'\n ? 'succeeded'\n : 'running';\n segments.push({\n startFraction: markFraction,\n endFraction: nextFraction,\n status: attemptStatus,\n });\n }\n } else if (mark.type === 'step_retrying') {\n // Retry wait: from this event to the next step_started (or end)\n segments.push({\n startFraction: markFraction,\n endFraction: nextFraction,\n status: 'retrying',\n });\n } else if (mark.type === 'step_failed') {\n // Terminal failure: from this event to the end\n if (markFraction < 0.999) {\n segments.push({\n startFraction: markFraction,\n endFraction: 1,\n status: 'failed',\n });\n }\n } else if (mark.type === 'step_completed') {\n // Terminal success: do nothing here since the preceding step_started\n // segment already terminates at this marker.\n }\n }\n\n return segments;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Hook segments\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Compute segments for a hook span.\n *\n * Timeline: [waiting] → [received] → [disposed]\n */\nfunction computeHookSegments(node: SpanNode): Segment[] {\n const events = node.events ? sortedEvents(node.events) : [];\n const { startTime, duration } = node;\n const segments: Segment[] = [];\n\n if (duration <= 0) return segments;\n\n const receivedEvent = events.find((e) => e.event.name === 'hook_received');\n const disposedEvent = events.find((e) => e.event.name === 'hook_disposed');\n\n if (!receivedEvent && !disposedEvent) {\n // Still waiting\n segments.push({ startFraction: 0, endFraction: 1, status: 'waiting' });\n return segments;\n }\n\n const receivedFraction = receivedEvent\n ? timeToFraction(receivedEvent.timestamp, startTime, duration)\n : null;\n const disposedFraction = disposedEvent\n ? timeToFraction(disposedEvent.timestamp, startTime, duration)\n : null;\n\n // Waiting period (before received)\n if (receivedFraction !== null && receivedFraction > 0.001) {\n segments.push({\n startFraction: 0,\n endFraction: receivedFraction,\n status: 'waiting',\n });\n } else if (receivedFraction === null && disposedFraction !== null) {\n // Disposed without receiving — waiting the whole time\n segments.push({\n startFraction: 0,\n endFraction: disposedFraction,\n status: 'waiting',\n });\n }\n\n // Received period\n if (receivedFraction !== null) {\n const end = disposedFraction ?? 1;\n segments.push({\n startFraction: receivedFraction,\n endFraction: end,\n status: 'received',\n });\n }\n\n // Post-disposed (if there's remaining span after disposal)\n if (disposedFraction !== null && disposedFraction < 0.999) {\n segments.push({\n startFraction: disposedFraction,\n endFraction: 1,\n status: 'succeeded',\n });\n }\n\n return segments;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Sleep segments\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Compute segments for a sleep span.\n *\n * Timeline: [sleeping] → [completed]\n */\nfunction computeSleepSegments(node: SpanNode): Segment[] {\n const events = node.events ? sortedEvents(node.events) : [];\n const { startTime, duration } = node;\n const segments: Segment[] = [];\n\n if (duration <= 0) return segments;\n\n const completedEvent = events.find((e) => e.event.name === 'wait_completed');\n\n if (!completedEvent) {\n // Still sleeping\n segments.push({ startFraction: 0, endFraction: 1, status: 'sleeping' });\n return segments;\n }\n\n const completedFraction = timeToFraction(\n completedEvent.timestamp,\n startTime,\n duration\n );\n\n if (completedFraction > 0.001) {\n segments.push({\n startFraction: 0,\n endFraction: completedFraction,\n status: 'sleeping',\n });\n }\n\n segments.push({\n startFraction: completedFraction,\n endFraction: 1,\n status: 'succeeded',\n });\n\n return segments;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Run segments\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Compute segments for a run span.\n *\n * Timeline: [queued] → [running] → [completed/failed]\n *\n * The queued period is derived from activeStartTime (run.startedAt).\n * A synthetic run_started event is injected at that timestamp so\n * the boundary is hoverable in the trace viewer.\n */\nfunction computeRunSegments(node: SpanNode): Segment[] {\n const events = node.events ? sortedEvents(node.events) : [];\n const { startTime, duration, activeStartTime } = node;\n const segments: Segment[] = [];\n\n if (duration <= 0) return segments;\n\n // V1 runs (specVersion 1) don't emit run lifecycle events (run_created,\n // run_started, run_completed). Detect this by checking for the absence of\n // run_created — it's always the first event for v2 runs and is always\n // loaded in the first page, so its absence reliably signals a v1 run.\n // For v1, fall back to the run entity's status from span.attributes.data.\n const hasRunCreated = events.some((e) => e.event.name === 'run_created');\n\n if (!hasRunCreated) {\n const runData = node.span.attributes?.data as\n | Record<string, unknown>\n | undefined;\n const runStatus = runData?.status as string | undefined;\n return computeV1RunSegments(\n startTime,\n duration,\n activeStartTime,\n runStatus\n );\n }\n\n const failedEvent = events.find((e) => e.event.name === 'run_failed');\n const completedEvent = events.find((e) => e.event.name === 'run_completed');\n\n // Queued period (from span start to activeStartTime)\n let cursor = 0;\n if (activeStartTime && activeStartTime > startTime) {\n const queuedFraction = timeToFraction(activeStartTime, startTime, duration);\n if (queuedFraction > 0.001) {\n segments.push({\n startFraction: 0,\n endFraction: queuedFraction,\n status: 'queued',\n });\n cursor = queuedFraction;\n }\n }\n\n if (failedEvent) {\n const failedFraction = timeToFraction(\n failedEvent.timestamp,\n startTime,\n duration\n );\n // Running until failure\n if (failedFraction > cursor + 0.001) {\n segments.push({\n startFraction: cursor,\n endFraction: failedFraction,\n status: 'running',\n });\n }\n segments.push({\n startFraction: failedFraction,\n endFraction: 1,\n status: 'failed',\n });\n } else if (completedEvent) {\n const completedFraction = timeToFraction(\n completedEvent.timestamp,\n startTime,\n duration\n );\n if (completedFraction > cursor + 0.001) {\n segments.push({\n startFraction: cursor,\n endFraction: completedFraction,\n status: 'running',\n });\n }\n segments.push({\n startFraction: completedFraction,\n endFraction: 1,\n status: 'succeeded',\n });\n } else {\n // Running to completion (or terminal events haven't loaded yet)\n segments.push({\n startFraction: cursor,\n endFraction: 1,\n status: 'running',\n });\n }\n\n return segments;\n}\n\n/**\n * Compute segments for a v1 run using only the run entity's status and\n * activeStartTime (derived from run.startedAt). V1 runs have no run\n * lifecycle events, so we infer the visual segments from entity fields.\n */\nfunction computeV1RunSegments(\n startTime: number,\n duration: number,\n activeStartTime: number | undefined,\n runStatus: string | undefined\n): Segment[] {\n const segments: Segment[] = [];\n\n let cursor = 0;\n if (activeStartTime && activeStartTime > startTime) {\n const queuedFraction = timeToFraction(activeStartTime, startTime, duration);\n if (queuedFraction > 0.001) {\n segments.push({\n startFraction: 0,\n endFraction: queuedFraction,\n status: 'queued',\n });\n cursor = queuedFraction;\n }\n }\n\n if (runStatus === 'failed') {\n segments.push({\n startFraction: cursor,\n endFraction: 1,\n status: 'failed',\n });\n } else if (runStatus === 'completed' || runStatus === 'cancelled') {\n segments.push({\n startFraction: cursor,\n endFraction: 1,\n status: 'succeeded',\n });\n } else {\n segments.push({\n startFraction: cursor,\n endFraction: 1,\n status: 'running',\n });\n }\n\n return segments;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Dispatcher\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface SegmentResult {\n segments: Segment[];\n boundaries: SegmentBoundary[];\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Boundary computation\n// ──────────────────────────────────────────────────────────────────────────\n\n/** Event names to human-readable labels */\nconst EVENT_LABELS: Record<string, string> = {\n step_started: 'Started',\n step_retrying: 'Retrying',\n step_failed: 'Failed',\n hook_created: 'Created',\n hook_received: 'Received',\n hook_disposed: 'Resolved',\n wait_created: 'Sleep started',\n wait_completed: 'Sleep completed',\n run_completed: 'Completed',\n run_failed: 'Run failed',\n step_completed: 'Completed',\n};\n\n/**\n * Extract boundaries from a span's events. Each boundary sits at the\n * fractional position of a relevant event within the span duration.\n * Only includes events that are used as segment boundaries (not at the\n * very start or very end of the span, to avoid edge clutter).\n */\nfunction computeBoundaries(\n node: SpanNode,\n relevantEventNames: string[]\n): SegmentBoundary[] {\n const events = node.events ? sortedEvents(node.events) : [];\n const { startTime, duration } = node;\n\n if (duration <= 0) return [];\n\n const boundaries: SegmentBoundary[] = [];\n for (const e of events) {\n if (!relevantEventNames.includes(e.event.name)) continue;\n\n const fraction = timeToFraction(e.timestamp, startTime, duration);\n // Skip boundaries at the very edges (< 1% or > 99%) to avoid clutter\n if (fraction < 0.01 || fraction > 0.99) continue;\n\n boundaries.push({\n fraction,\n label: EVENT_LABELS[e.event.name] ?? e.event.name,\n offsetMs: e.timestamp - startTime,\n });\n }\n\n return boundaries;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Dispatcher\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Compute the event-based segments and boundaries for a span based on its resource type.\n * Returns empty arrays for 'default' (generic OTEL) spans.\n */\nexport function computeSegments(\n resourceType: ResourceType,\n node: SpanNode\n): SegmentResult {\n switch (resourceType) {\n case 'step':\n return {\n segments: computeStepSegments(node),\n boundaries: computeBoundaries(node, [\n 'step_started',\n 'step_retrying',\n 'step_failed',\n 'step_completed',\n ]),\n };\n case 'hook':\n return {\n segments: computeHookSegments(node),\n boundaries: computeBoundaries(node, [\n 'hook_created',\n 'hook_received',\n 'hook_disposed',\n ]),\n };\n case 'sleep':\n return {\n segments: computeSleepSegments(node),\n boundaries: computeBoundaries(node, ['wait_created', 'wait_completed']),\n };\n case 'run':\n return {\n segments: computeRunSegments(node),\n boundaries: computeBoundaries(node, ['run_completed', 'run_failed']),\n };\n default:\n return { segments: [], boundaries: [] };\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"span-strategies.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/span-strategies.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RefObject } from 'react';\nimport type { RootNode, ScrollSnapshot, VisibleSpan } from '../types';\nimport { MARKER_HEIGHT, ROW_HEIGHT, ROW_PADDING } from '../util/constants';\n\n/**\n * The resource type of a workflow span, read from span.attributes.resource.\n * Falls back to 'default' for non-workflow (generic OTEL) spans.\n */\nexport type ResourceType = 'run' | 'step' | 'hook' | 'sleep' | 'default';\n\n/** Minimum rendered width so very short spans are always visible */\nconst MIN_SPAN_WIDTH = 4;\n\n/**\n * Layout result computed by a span strategy. Controls how the span\n * is sized and positioned in the timeline.\n */\nexport interface SpanLayout {\n /** The rendered width in pixels */\n width: number;\n /** The actual duration-based width (before min-width clamping) */\n actualWidth: number;\n /** The rendered height in pixels */\n height: number;\n /** The y position in pixels */\n top: number;\n /** The x position in pixels (from left) */\n left: number;\n /** Whether the span is considered \"small\" (< 64px actual width) */\n isSmall: boolean;\n /** Whether the span is considered \"huge\" (>= 500px actual width) */\n isHuge: boolean;\n /** Whether the span is currently hovered (with hover eligibility) */\n isHovered: boolean;\n /** Whether the span is expanded (hovered or selected) — controls sizing */\n isExpanded: boolean;\n /** Whether the span is near the right side of the visible area */\n isNearRightSide: boolean;\n}\n\n/**\n * Reads the resource type from a span's attributes.\n */\nexport function getResourceType(node: VisibleSpan): ResourceType {\n const resource = node.span.attributes?.resource;\n if (\n resource === 'run' ||\n resource === 'step' ||\n resource === 'hook' ||\n resource === 'sleep'\n ) {\n return resource;\n }\n return 'default';\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Shared helpers\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction computeIsSmall(actualWidth: number): boolean {\n return actualWidth < 64;\n}\n\nfunction computeIsHuge(actualWidth: number): boolean {\n return actualWidth >= 500;\n}\n\nfunction computeIsHovered(node: VisibleSpan, isHuge: boolean): boolean {\n return node.isHovered && !isHuge && node.isHighlighted !== false;\n}\n\nfunction computeIsNearRightSide(\n node: VisibleSpan,\n root: RootNode,\n scrollSnapshotRef: RefObject<ScrollSnapshot | undefined>,\n isHovered: boolean\n): boolean {\n if (!isHovered) return false;\n\n let visibleDuration = root.duration;\n let visibleEndTime = root.endTime;\n const snapshot = scrollSnapshotRef.current;\n if (snapshot) {\n visibleDuration = snapshot.endTime - snapshot.startTime;\n visibleEndTime = snapshot.endTime;\n }\n return visibleEndTime - node.startTime < 0.25 * visibleDuration;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Default layout (used by step, hook, run, default — all behave the same today)\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction computeDefaultLayout(\n node: VisibleSpan,\n root: RootNode,\n scale: number,\n scrollSnapshotRef: RefObject<ScrollSnapshot | undefined>\n): SpanLayout {\n const left = (node.startTime - root.startTime) * scale;\n let top = MARKER_HEIGHT + (ROW_HEIGHT + ROW_PADDING) * node.row;\n const actualWidth = node.duration * scale;\n const width = Math.max(actualWidth, MIN_SPAN_WIDTH);\n let height = ROW_HEIGHT;\n\n const isHuge = computeIsHuge(actualWidth);\n const isSmall = computeIsSmall(actualWidth);\n const isHovered = computeIsHovered(node, isHuge);\n const isExpanded = isHovered || Boolean(node.isSelected);\n\n if (isSmall && !isExpanded) {\n height *= 0.4;\n top += (ROW_HEIGHT - height) * 0.5;\n }\n\n const isNearRightSide = computeIsNearRightSide(\n node,\n root,\n scrollSnapshotRef,\n isExpanded\n );\n\n return {\n width,\n actualWidth,\n height,\n top,\n left,\n isSmall,\n isHuge,\n isHovered,\n isExpanded,\n isNearRightSide,\n };\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Per-type layout functions\n// Each returns the same result today but provides a clear extension point.\n// ──────────────────────────────────────────────────────────────────────────\n\nexport function getRunLayout(\n node: VisibleSpan,\n root: RootNode,\n scale: number,\n scrollSnapshotRef: RefObject<ScrollSnapshot | undefined>\n): SpanLayout {\n return computeDefaultLayout(node, root, scale, scrollSnapshotRef);\n}\n\nexport function getStepLayout(\n node: VisibleSpan,\n root: RootNode,\n scale: number,\n scrollSnapshotRef: RefObject<ScrollSnapshot | undefined>\n): SpanLayout {\n return computeDefaultLayout(node, root, scale, scrollSnapshotRef);\n}\n\nexport function getHookLayout(\n node: VisibleSpan,\n root: RootNode,\n scale: number,\n scrollSnapshotRef: RefObject<ScrollSnapshot | undefined>\n): SpanLayout {\n return computeDefaultLayout(node, root, scale, scrollSnapshotRef);\n}\n\nexport function getSleepLayout(\n node: VisibleSpan,\n root: RootNode,\n scale: number,\n scrollSnapshotRef: RefObject<ScrollSnapshot | undefined>\n): SpanLayout {\n return computeDefaultLayout(node, root, scale, scrollSnapshotRef);\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Dispatcher\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Computes the layout for a span based on its resource type.\n */\nexport function getSpanLayout(\n resourceType: ResourceType,\n node: VisibleSpan,\n root: RootNode,\n scale: number,\n scrollSnapshotRef: RefObject<ScrollSnapshot | undefined>\n): SpanLayout {\n switch (resourceType) {\n case 'run':\n return getRunLayout(node, root, scale, scrollSnapshotRef);\n case 'step':\n return getStepLayout(node, root, scale, scrollSnapshotRef);\n case 'hook':\n return getHookLayout(node, root, scale, scrollSnapshotRef);\n case 'sleep':\n return getSleepLayout(node, root, scale, scrollSnapshotRef);\n default:\n return computeDefaultLayout(node, root, scale, scrollSnapshotRef);\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/ui.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,MAAM,MAAM,4BAA4B,CAAC;AAEhD,6BAA6B;AAC7B,MAAM,aAAa,GAA2B;IAC5C,UAAU,EAAE,oBAAoB;IAChC,UAAU,EAAE,oBAAoB;CACjC,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,EACxB,IAAI,GAAG,EAAE,EACT,KAAK,GAAG,UAAU,GAInB;IACC,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,EAAW,CAAC;IAChE,OAAO,CACL,eACE,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,KAAK,kCAGZ,oCAAoB,EACpB,eACE,CAAC,EAAC,sBAAsB,EACxB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,IACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAE,IAAI,GAAG,EAAE,EAAqB;IAC9D,OAAO,CACL,eACE,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,uBAEX,SAAS,EAAE,MAAM,CAAC,iBAAiB,aAEnC,2CAA2B,EAC3B,eACE,CAAC,EAAC,cAAc,EAChB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,GACtB,IACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,EAChC,IAAI,GAAG,EAAE,EACT,KAAK,GAAG,UAAU,GAInB;IACC,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,EAAW,CAAC;IAChE,OAAO,CACL,eACE,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,KAAK,kCAGZ,6CAA6B,EAC7B,eACE,CAAC,EAAC,yBAAyB,EAC3B,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,GACtB,EACF,eACE,CAAC,EAAC,0DAA0D,EAC5D,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,IACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI,CAClB,KAAsE;IAEtE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACjE,MAAM,OAAO,GAAQ,MAAM,IAAI,GAAG,CAAC;IACnC,IAAI,OAAO,KAAK,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAChC,OAAO,CACL,eAAM,SAAS,EAAE,SAAS,KAAM,IAAI,YACjC,QAAQ,GACJ,CACR,CAAC;IACJ,CAAC;IACD,OAAO,CACL,YAAG,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,KAAM,IAAI,YAC1C,QAAQ,GACP,CACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,KAEC;IAED,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAC5D,OAAO,CACL,eAAO,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,YACvD,QAAQ,GACP,CACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,GAIV;IACC,OAAO,cAAK,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,YAAG,QAAQ,GAAO,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,EACvB,KAAK,EACL,MAAM,EACN,OAAO,GAKR;IACC,OAAO,CACL,eACE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,IAAI,MAAM,CAAC,eAAe,CAAC,EACnE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,wBAExB,CACH,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\nimport { clsx } from 'clsx';\nimport type { AnchorHTMLAttributes, ReactNode } from 'react';\nimport styles from '../trace-viewer.module.css';\n\n// Color token mapping helper\nconst colorTokenMap: Record<string, string> = {\n 'gray-700': 'var(--ds-gray-700)',\n 'gray-900': 'var(--ds-gray-900)',\n};\n\nexport function IconCross({\n size = 16,\n color = 'gray-700',\n}: {\n size?: number;\n color?: string;\n}): ReactNode {\n const style = { color: colorTokenMap[color] || color } as const;\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n style={style}\n aria-hidden\n >\n <title>Cross</title>\n <path\n d=\"M6 6l12 12M18 6L6 18\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\nexport function IconChevronDown({ size = 16 }: { size?: number }): ReactNode {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n aria-hidden\n className={styles.detailHeadingIcon}\n >\n <title>Chevron Down</title>\n <path\n d=\"M6 9l6 6 6-6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nexport function IconExternalSmall({\n size = 16,\n color = 'gray-900',\n}: {\n size?: number;\n color?: string;\n}): ReactNode {\n const style = { color: colorTokenMap[color] || color } as const;\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n style={style}\n aria-hidden\n >\n <title>External Small</title>\n <path\n d=\"M14 4h6m0 0v6m0-6L10 14\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M20 14v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h4\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\nexport function Link(\n props: AnchorHTMLAttributes<HTMLAnchorElement> & { as?: 'a' | 'span' }\n): ReactNode {\n const { as: asProp, className, href, children, ...rest } = props;\n const Element: any = asProp || 'a';\n if (Element === 'span' || !href) {\n return (\n <span className={className} {...rest}>\n {children}\n </span>\n );\n }\n return (\n <a className={className} href={href} {...rest}>\n {children}\n </a>\n );\n}\n\nexport function ButtonLink(\n props: AnchorHTMLAttributes<HTMLAnchorElement> & {\n size?: 'small' | 'medium' | 'large';\n }\n): ReactNode {\n const { className, children, size: _size, ...rest } = props;\n return (\n <a {...rest} className={clsx(styles.buttonLink, className)}>\n {children}\n </a>\n );\n}\n\nexport function Note({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}): ReactNode {\n return <div className={clsx(styles.note, className)}>{children}</div>;\n}\n\nexport function Skeleton({\n width,\n height,\n rounded,\n}: {\n width: number;\n height: number;\n rounded?: boolean;\n}): ReactNode {\n return (\n <span\n className={clsx(styles.skeleton, rounded && styles.skeletonRounded)}\n style={{ width, height }}\n aria-hidden\n />\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"zoom-button.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/zoom-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,OAAO,EAAkB,WAAW,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,MAAM,MAAM,4BAA4B,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,UAAU,UAAU;IACxB,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,EAAE,CAAC;IAEtC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAS,EAAE;QACtC,QAAQ,CAAC;YACP,IAAI,EAAE,kBAAkB;YACxB,SAAS,EAAE,CAAC;SACb,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,MAAM,SAAS,GAAG,WAAW,CAAC,GAAS,EAAE;QACvC,QAAQ,CAAC;YACP,IAAI,EAAE,kBAAkB;YACxB,SAAS,EAAE,CAAC,CAAC;SACd,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,MAAM,WAAW,GAAG,WAAW,CAAC,GAAS,EAAE;QACzC,QAAQ,CAAC;YACP,IAAI,EAAE,kBAAkB;YACxB,SAAS,EAAE,CAAC;SACb,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,OAAO,CACL,eAAK,SAAS,EAAE,MAAM,CAAC,eAAe,aACpC,+BACa,UAAU,EACrB,SAAS,EAAE,MAAM,CAAC,UAAU,EAC5B,OAAO,EAAE,SAAS,EAClB,IAAI,EAAC,QAAQ,YAEb,KAAC,WAAW,IAAC,IAAI,EAAE,EAAE,GAAI,GAClB,EACT,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,GAAI,EAClC,+BACa,YAAY,EACvB,SAAS,EAAE,MAAM,CAAC,UAAU,EAC5B,OAAO,EAAE,WAAW,EACpB,IAAI,EAAC,QAAQ,YAEb,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,GAChB,EACT,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,GAAI,EAClC,+BACa,SAAS,EACpB,SAAS,EAAE,MAAM,CAAC,UAAU,EAC5B,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAC,QAAQ,YAEb,KAAC,UAAU,IAAC,IAAI,EAAE,EAAE,GAAI,GACjB,IACL,CACP,CAAC;AACJ,CAAC","sourcesContent":["'use client';\nimport { type ReactNode, useCallback } from 'react';\nimport { useTraceViewer } from '../context';\nimport styles from '../trace-viewer.module.css';\nimport { IconMinus, IconZoomIn, IconZoomOut } from './zoom-icons';\n\nexport function ZoomButton(): ReactNode {\n const { dispatch } = useTraceViewer();\n\n const onZoomIn = useCallback((): void => {\n dispatch({\n type: 'adjustScaleRatio',\n direction: 1,\n });\n }, [dispatch]);\n\n const onZoomOut = useCallback((): void => {\n dispatch({\n type: 'adjustScaleRatio',\n direction: -1,\n });\n }, [dispatch]);\n\n const onResetZoom = useCallback((): void => {\n dispatch({\n type: 'adjustScaleRatio',\n direction: 0,\n });\n }, [dispatch]);\n\n return (\n <div className={styles.zoomButtonGroup}>\n <button\n aria-label=\"Zoom Out\"\n className={styles.zoomButton}\n onClick={onZoomOut}\n type=\"button\"\n >\n <IconZoomOut size={18} />\n </button>\n <div className={styles.divider} />\n <button\n aria-label=\"Reset Zoom\"\n className={styles.zoomButton}\n onClick={onResetZoom}\n type=\"button\"\n >\n <IconMinus size={18} />\n </button>\n <div className={styles.divider} />\n <button\n aria-label=\"Zoom In\"\n className={styles.zoomButton}\n onClick={onZoomIn}\n type=\"button\"\n >\n <IconZoomIn size={18} />\n </button>\n </div>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"zoom-icons.js","sourceRoot":"","sources":["../../../../src/components/trace-viewer/components/zoom-icons.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,UAAU,CAAC,EAAE,IAAI,GAAG,EAAE,EAAqB;IACzD,OAAO,CACL,eAAK,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,kCAC7D,sCAAsB,EACtB,eACE,CAAC,EAAC,uCAAuC,EACzC,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,GACf,EACF,eACE,CAAC,EAAC,gBAAgB,EAClB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,EACF,eACE,CAAC,EAAC,iBAAiB,EACnB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,IACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAE,IAAI,GAAG,EAAE,EAAqB;IAC1D,OAAO,CACL,eAAK,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,kCAC7D,uCAAuB,EACvB,eACE,CAAC,EAAC,uCAAuC,EACzC,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,GACf,EACF,eACE,CAAC,EAAC,SAAS,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,EACF,eACE,CAAC,EAAC,iBAAiB,EACnB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,IACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAE,IAAI,GAAG,EAAE,EAAqB;IACxD,OAAO,CACL,eAAK,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,kCAC7D,oCAAoB,EACpB,eACE,CAAC,EAAC,UAAU,EACZ,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,IACE,CACP,CAAC;AACJ,CAAC","sourcesContent":["import type { ReactNode } from 'react';\n\nexport function IconZoomIn({ size = 16 }: { size?: number }): ReactNode {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden>\n <title>Zoom In</title>\n <path\n d=\"M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n />\n <path\n d=\"M11 8v6M8 11h6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M20 20l-3.5-3.5\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\nexport function IconZoomOut({ size = 16 }: { size?: number }): ReactNode {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden>\n <title>Zoom Out</title>\n <path\n d=\"M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n />\n <path\n d=\"M8 11h6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M20 20l-3.5-3.5\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\nexport function IconMinus({ size = 16 }: { size?: number }): ReactNode {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden>\n <title>Minus</title>\n <path\n d=\"M6 12h12\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/components/trace-viewer/context.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport type { Dispatch, MutableRefObject, ReactNode, Reducer } from 'react';\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useReducer,\n useRef,\n} from 'react';\nimport type {\n GetQuickLinks,\n MemoCache,\n MemoCacheKey,\n QuickLink,\n Resource,\n RootNode,\n ScrollSnapshot,\n SpanNode,\n VisibleSpanEvent,\n} from './types';\nimport {\n MAP_HEIGHT,\n MARKER_HEIGHT,\n ROW_HEIGHT,\n ROW_PADDING,\n SEARCH_GAP,\n SEARCH_HEIGHT,\n TIMELINE_PADDING,\n} from './util/constants';\nimport { detectScrollbarWidth } from './util/scrollbar-width';\n\nexport interface TraceViewerState {\n /**\n * The root node for the tree\n */\n root: RootNode;\n /**\n * A map of spanId to span nodes\n */\n spanMap: Record<string, SpanNode>;\n /**\n * A map of resource name to resource\n */\n resourceMap: Record<string, Resource['attributes']>;\n /**\n * The current (debounced) search input value\n */\n filter: string;\n /**\n * The span that is currently focused and visible in the panel\n */\n selected: SpanNode | null;\n /**\n * The initial scale of the trace. At this scale the entire trace is visible\n */\n baseScale: number;\n /**\n * The multiplier of the base scale to get the current scale\n */\n scaleRatio: number;\n /**\n * The scale of 1ms in pixels\n */\n scale: number;\n /**\n * The width of the entire trace viewer in pixels\n */\n width: number;\n /**\n * The height of the entire trace viewer in pixels\n */\n height: number;\n /**\n * The width of the timeline view in pixels\n */\n timelineWidth: number;\n /**\n * The height of the timeline view in pixels\n */\n timelineHeight: number;\n /**\n * The width of the side panel in pixels\n */\n panelWidth: number;\n /**\n * The height of the side panel in pixels\n */\n panelHeight: number;\n /**\n * The width of scrollbars on this device\n */\n scrollbarWidth: number;\n /**\n * A ref for the timeline element\n */\n timelineRef: MutableRefObject<HTMLDivElement | null>;\n /**\n * A ref for updating timeline scroll position immediately after a scale operation\n */\n scrollSnapshotRef: MutableRefObject<ScrollSnapshot | undefined>;\n /**\n * A reference for the last time each node was mutated. Used for more efficent control\n * of what React re-renders and when.\n */\n memoCacheRef: MutableRefObject<MemoCache>;\n /**\n * A constant, wrapped version of the getQuickLinks property with caching\n */\n getQuickLinks: GetQuickLinks;\n /**\n * Whether the panel is being rendered attached to the timeline\n */\n withPanel: boolean;\n /**\n * Whether the trace viewer is small enough that it should be in mobile mode\n */\n isMobile: boolean;\n /**\n * A function to provide custom class names for spans.\n */\n customSpanClassNameFunc?: (span: SpanNode) => string;\n /**\n * A function to provide custom class names for span events.\n */\n customSpanEventClassNameFunc?: (event: VisibleSpanEvent) => string;\n}\n\nexport type TraceViewerAction =\n | {\n type: 'setRoot';\n root: RootNode;\n spanMap: Record<string, SpanNode>;\n resources: Resource[];\n }\n | {\n type: 'setSize';\n width: number;\n height: number;\n }\n | {\n type: 'setPanelWidth';\n width: number;\n }\n | {\n type: 'setFilter';\n filter: string;\n }\n | {\n type: 'deselect';\n }\n | {\n type: 'select';\n id: string;\n }\n | {\n type: 'escape';\n }\n | {\n type: 'toggleSelection';\n id: string;\n }\n | {\n type: 'detectBaseScale';\n }\n | {\n type: 'setScale';\n scale: number;\n }\n | {\n type: 'resetScale';\n }\n | {\n type: 'scaleToNode';\n id: string;\n }\n | {\n type: 'scaleToRange';\n t1: number;\n t2: number;\n }\n | {\n type: 'adjustScaleRatio';\n direction: -1 | 0 | 1;\n }\n | {\n type: 'trackpadScale';\n delta: number;\n anchorT: number;\n anchorX: number;\n }\n | {\n type: 'minScale';\n }\n | {\n type: 'setScrollSnapshot';\n /**\n * The time that will remain the same location after scaling\n */\n anchorT: number;\n /**\n * The anchor point relative to the timeline's left position\n */\n anchorX: number;\n }\n | {\n type: 'setWithPanel';\n withPanel: boolean;\n }\n | {\n type: 'forceRender';\n }\n | {\n /** Like setRoot but preserves scroll position and memo cache (for incremental data updates) */\n type: 'updateRoot';\n root: RootNode;\n spanMap: Record<string, SpanNode>;\n resources: Resource[];\n };\n\nexport interface TraceViewerContextProps {\n state: TraceViewerState;\n dispatch: Dispatch<TraceViewerAction>;\n}\n\nexport const initialState: TraceViewerState = {\n root: {\n startTime: 0,\n endTime: 1,\n duration: 1,\n depth: 0,\n children: [],\n },\n spanMap: {},\n resourceMap: {},\n filter: '',\n selected: null,\n baseScale: 1,\n scaleRatio: 1,\n scale: 1,\n width: 640,\n height: 480,\n timelineWidth: 640,\n timelineHeight: 480,\n panelWidth: 380,\n panelHeight: 480,\n scrollbarWidth: 0,\n timelineRef: { current: null },\n scrollSnapshotRef: { current: undefined },\n memoCacheRef: { current: new Map() },\n getQuickLinks: () => [],\n withPanel: false,\n isMobile: false,\n};\n\nconst getMinScale = (state: TraceViewerState): number => {\n return (state.timelineWidth - state.scrollbarWidth) / state.root.duration;\n};\n\nexport const TraceViewerContext = createContext<TraceViewerContextProps>({\n state: initialState,\n dispatch: () => {\n // noop\n },\n});\nTraceViewerContext.displayName = 'TraceViewerContext';\n\nconst reducer: Reducer<TraceViewerState, TraceViewerAction> = (\n state,\n action\n) => {\n switch (action.type) {\n case 'setRoot':\n state.scrollSnapshotRef.current = undefined;\n state.memoCacheRef.current.clear();\n return reducer(\n {\n ...state,\n root: action.root,\n spanMap: action.spanMap,\n resourceMap: Object.fromEntries(\n action.resources.map(({ name, attributes }) => [name, attributes])\n ),\n },\n {\n type: 'detectBaseScale',\n }\n );\n case 'setSize': {\n const lowerHeight =\n action.height - MAP_HEIGHT - SEARCH_HEIGHT - 3 * SEARCH_GAP;\n\n const isMobile = state.withPanel && action.width <= 768;\n\n let newState = {\n ...state,\n width: action.width,\n height: action.height,\n timelineWidth:\n action.width -\n Number(Boolean(state.selected && state.withPanel && !isMobile)) *\n state.panelWidth,\n timelineHeight: lowerHeight,\n panelHeight: lowerHeight,\n isMobile,\n };\n\n if (newState.width !== state.width) {\n newState = reducer(newState, {\n type: 'detectBaseScale',\n });\n }\n\n return newState;\n }\n case 'setPanelWidth': {\n const panelWidth = Math.max(\n 240,\n Math.min(action.width, state.width - 240)\n );\n const timelineWidth =\n state.withPanel && state.selected && !state.isMobile\n ? state.width - panelWidth\n : state.width;\n return reducer(\n {\n ...state,\n timelineWidth,\n panelWidth,\n },\n {\n type: 'detectBaseScale',\n }\n );\n }\n case 'setFilter':\n return {\n ...state,\n filter: action.filter,\n };\n case 'deselect':\n return reducer(\n {\n ...state,\n selected: null,\n timelineWidth: state.width,\n },\n {\n type: 'detectBaseScale',\n }\n );\n case 'select': {\n const node = state.spanMap[action.id];\n if (!node) {\n return state;\n }\n\n return reducer(\n {\n ...state,\n selected: node,\n timelineWidth:\n state.width -\n (state.withPanel && !state.isMobile ? state.panelWidth : 0),\n },\n {\n type: 'detectBaseScale',\n }\n );\n }\n case 'escape': {\n if (state.selected) {\n return reducer(state, {\n type: 'deselect',\n });\n }\n return reducer(state, {\n type: 'resetScale',\n });\n }\n case 'toggleSelection': {\n let newState = state;\n if (state.selected) {\n newState = reducer(newState, {\n type: 'deselect',\n });\n }\n if (state.selected?.span.spanId === action.id) {\n return newState;\n }\n return reducer(newState, {\n type: 'select',\n id: action.id,\n });\n }\n case 'detectBaseScale': {\n const baseScale =\n (state.timelineWidth - state.scrollbarWidth) / state.root.duration;\n\n return reducer(\n {\n ...state,\n baseScale,\n scale: baseScale * state.scaleRatio,\n },\n {\n type: 'minScale',\n }\n );\n }\n case 'setScale':\n return {\n ...state,\n scaleRatio: action.scale,\n scale: state.baseScale * action.scale,\n };\n case 'resetScale':\n return reducer(state, {\n type: 'scaleToRange',\n t1: state.root.startTime,\n t2: state.root.endTime,\n });\n case 'scaleToNode': {\n const node = state.spanMap[action.id];\n if (!node) {\n return state;\n }\n return reducer(\n reducer(state, {\n type: 'setScale',\n scale:\n (state.width -\n state.scrollbarWidth -\n (state.withPanel && !state.isMobile ? state.panelWidth : 0)) /\n node.duration /\n state.baseScale,\n }),\n {\n type: 'setScrollSnapshot',\n anchorT: node.startTime - state.root.startTime,\n anchorX: 0,\n }\n );\n }\n case 'scaleToRange': {\n const duration = Math.abs(action.t1 - action.t2);\n\n return reducer(\n reducer(state, {\n type: 'setScale',\n scale:\n (state.width -\n state.scrollbarWidth -\n (state.selected && state.withPanel ? state.panelWidth : 0)) /\n duration /\n state.baseScale,\n }),\n {\n type: 'setScrollSnapshot',\n anchorT: Math.min(action.t1, action.t2) - state.root.startTime,\n anchorX: 0,\n }\n );\n }\n case 'adjustScaleRatio': {\n let { scaleRatio } = state;\n switch (action.direction) {\n case -1:\n scaleRatio *= 0.8;\n break;\n case 1:\n scaleRatio *= 1.25;\n break;\n default:\n scaleRatio = 1;\n break;\n }\n\n const $timeline = state.timelineRef.current;\n if (!$timeline) {\n console.warn('timelineRef is null');\n return state;\n }\n\n const { clientWidth, scrollLeft } = $timeline;\n\n return reducer(\n reducer(\n {\n ...state,\n scaleRatio,\n scale: state.baseScale * scaleRatio,\n },\n {\n type: 'minScale',\n }\n ),\n {\n type: 'setScrollSnapshot',\n anchorT: (scrollLeft + clientWidth * 0.5) / state.scale,\n anchorX: clientWidth * 0.5,\n }\n );\n }\n case 'trackpadScale': {\n const minScaleRatio = getMinScale(state) / state.baseScale;\n const scaleRatio = Math.max(\n minScaleRatio,\n state.scaleRatio *\n (1 +\n 0.2 * Math.sign(action.delta) * Math.sqrt(Math.abs(action.delta)))\n );\n\n return reducer(\n {\n ...state,\n scaleRatio,\n scale: state.baseScale * scaleRatio,\n },\n {\n type: 'setScrollSnapshot',\n anchorT: action.anchorT,\n anchorX: action.anchorX,\n }\n );\n }\n case 'minScale': {\n const minScale = getMinScale(state);\n if (state.scale >= minScale) return state;\n return {\n ...state,\n scale: minScale,\n scaleRatio: minScale / state.baseScale,\n };\n }\n case 'setScrollSnapshot': {\n const $timeline = state.timelineRef.current;\n if (!$timeline) return state;\n\n const { anchorT, anchorX } = action;\n\n const scrollLeft = anchorT * state.scale - anchorX;\n const { scrollTop } = $timeline;\n const startRow =\n (scrollTop - MARKER_HEIGHT - TIMELINE_PADDING) /\n (ROW_HEIGHT + ROW_PADDING);\n const endRow =\n startRow + Math.ceil(state.timelineHeight / (ROW_HEIGHT + ROW_PADDING));\n\n state.scrollSnapshotRef.current = {\n anchorT,\n anchorX,\n scrollLeft,\n scrollTop,\n startTime: state.root.startTime + scrollLeft / state.scale,\n endTime:\n state.root.startTime +\n (scrollLeft + state.timelineWidth) / state.scale,\n startRow,\n endRow,\n scale: state.scale,\n };\n\n return state;\n }\n case 'setWithPanel': {\n if (state.withPanel === action.withPanel) return state;\n const timelineWidth =\n action.withPanel && state.selected && !state.isMobile\n ? state.width - state.panelWidth\n : state.width;\n return reducer(\n {\n ...state,\n withPanel: action.withPanel,\n timelineWidth,\n },\n {\n type: 'detectBaseScale',\n }\n );\n }\n case 'forceRender':\n state.memoCacheRef.current.set('', {});\n return {\n ...state,\n };\n case 'updateRoot':\n // Incremental update: preserve scroll snapshot and only invalidate\n // memo cache for spans whose data may have changed\n state.memoCacheRef.current.set('', {});\n return reducer(\n {\n ...state,\n root: action.root,\n spanMap: action.spanMap,\n resourceMap: Object.fromEntries(\n action.resources.map(({ name, attributes }) => [name, attributes])\n ),\n },\n {\n type: 'detectBaseScale',\n }\n );\n }\n};\n\nexport function TraceViewerContextProvider({\n getQuickLinks,\n withPanel = false,\n children,\n customSpanClassNameFunc,\n customSpanEventClassNameFunc,\n customPanelComponent = null,\n}: {\n getQuickLinks?: GetQuickLinks;\n withPanel?: boolean;\n children: ReactNode;\n customSpanClassNameFunc?: (span: SpanNode) => string;\n customSpanEventClassNameFunc?: (event: VisibleSpanEvent) => string;\n customPanelComponent?: ReactNode;\n}): ReactNode {\n const timelineRef = useRef<HTMLDivElement>(null);\n const scrollSnapshotRef = useRef<ScrollSnapshot>(undefined);\n const getQuickLinksRef = useRef(getQuickLinks);\n getQuickLinksRef.current = getQuickLinks;\n const memoCacheRef = useRef(new Map<string, MemoCacheKey>());\n const quickLinksCache = useRef(new Map<string, QuickLink[]>());\n const [state, dispatch] = useReducer(reducer, initialState, (initial) => {\n return {\n ...initial,\n scrollbarWidth: detectScrollbarWidth(),\n timelineRef,\n scrollSnapshotRef,\n customSpanClassNameFunc,\n customSpanEventClassNameFunc,\n memoCacheRef,\n withPanel,\n getQuickLinks: (span) => {\n const cacheKey = span.spanId;\n const existing = quickLinksCache.current.get(cacheKey);\n if (existing) return existing;\n\n const value = getQuickLinksRef.current?.(span) || [];\n quickLinksCache.current.set(cacheKey, value);\n return value;\n },\n };\n });\n\n useEffect(\n () =>\n dispatch({\n type: 'setWithPanel',\n withPanel,\n }),\n [withPanel]\n );\n\n const value: TraceViewerContextProps = useMemo(\n () => ({ state, dispatch }),\n [state, dispatch]\n );\n\n return (\n <CustomPanelContext.Provider value={customPanelComponent}>\n <TraceViewerContext.Provider value={value}>\n {children}\n </TraceViewerContext.Provider>\n </CustomPanelContext.Provider>\n );\n}\n\nexport const useTraceViewer = (): TraceViewerContextProps =>\n useContext(TraceViewerContext);\n\n/**\n * Separate context for the custom panel component. This is intentionally\n * outside the useReducer state so that the panel re-renders reactively\n * when props like spanDetailData change.\n */\nconst CustomPanelContext = createContext<ReactNode | null>(null);\n\nexport const useCustomPanelComponent = (): ReactNode | null =>\n useContext(CustomPanelContext);\n"]}