@workflow/web-shared 5.0.0-beta.3 → 5.0.0-beta.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -10
- package/dist/components/error-boundary.js +1 -1
- package/dist/components/event-list-view.d.ts +46 -1
- package/dist/components/event-list-view.d.ts.map +1 -1
- package/dist/components/event-list-view.js +228 -90
- package/dist/components/hook-actions.js +1 -1
- package/dist/components/index.d.ts +6 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -2
- package/dist/components/new-trace-viewer/components/copy-button.js +3 -3
- package/dist/components/new-trace-viewer/components/detail-panel-width.d.ts +34 -0
- package/dist/components/new-trace-viewer/components/detail-panel-width.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/detail-panel-width.js +67 -0
- package/dist/components/new-trace-viewer/components/detail-panel.d.ts +14 -0
- package/dist/components/new-trace-viewer/components/detail-panel.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/detail-panel.js +122 -0
- package/dist/components/new-trace-viewer/components/draggable-border.d.ts +31 -0
- package/dist/components/new-trace-viewer/components/draggable-border.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/draggable-border.js +140 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts +4 -2
- package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/event-list.js +22 -13
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts +18 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +54 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts +25 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +101 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
- package/dist/components/new-trace-viewer/components/minimap.d.ts +14 -0
- package/dist/components/new-trace-viewer/components/minimap.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/minimap.js +337 -0
- package/dist/components/new-trace-viewer/components/pane-constants.d.ts +14 -0
- package/dist/components/new-trace-viewer/components/pane-constants.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/pane-constants.js +16 -0
- package/dist/components/new-trace-viewer/components/span-markers.d.ts +46 -0
- package/dist/components/new-trace-viewer/components/span-markers.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/span-markers.js +85 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts +3 -7
- package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/split-pane.js +25 -84
- package/dist/components/new-trace-viewer/components/timeline.d.ts +19 -15
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/timeline.js +229 -111
- package/dist/components/new-trace-viewer/components/timeline.module.css +46 -0
- package/dist/components/new-trace-viewer/components/trace-shortcut-helper.d.ts +5 -0
- package/dist/components/new-trace-viewer/components/trace-shortcut-helper.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/trace-shortcut-helper.js +55 -0
- package/dist/components/new-trace-viewer/components/trace-shortcut-helper.module.css +20 -0
- package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts +2 -0
- package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.js +26 -0
- package/dist/components/new-trace-viewer/components/use-element-width.d.ts +8 -0
- package/dist/components/new-trace-viewer/components/use-element-width.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/use-element-width.js +25 -0
- package/dist/components/new-trace-viewer/components/use-row-window.d.ts +34 -0
- package/dist/components/new-trace-viewer/components/use-row-window.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/use-row-window.js +107 -0
- package/dist/components/new-trace-viewer/context.d.ts +3 -1
- package/dist/components/new-trace-viewer/context.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/context.js +9 -10
- package/dist/components/new-trace-viewer/icons.js +3 -3
- package/dist/components/new-trace-viewer/search.d.ts +19 -0
- package/dist/components/new-trace-viewer/search.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/search.js +134 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts +6 -3
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/trace-viewer.js +167 -162
- package/dist/components/new-trace-viewer/types.d.ts +2 -0
- package/dist/components/new-trace-viewer/types.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/types.js +2 -2
- package/dist/components/new-trace-viewer/utils.d.ts +48 -13
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/utils.js +135 -107
- package/dist/components/run-trace-view.d.ts +5 -7
- package/dist/components/run-trace-view.d.ts.map +1 -1
- package/dist/components/run-trace-view.js +3 -3
- package/dist/components/sidebar/attribute-panel.d.ts +4 -1
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +133 -113
- package/dist/components/sidebar/attributes-block.d.ts +40 -0
- package/dist/components/sidebar/attributes-block.d.ts.map +1 -0
- package/dist/components/sidebar/attributes-block.js +140 -0
- package/dist/components/sidebar/conversation-view.js +1 -1
- package/dist/components/sidebar/copyable-data-block.d.ts +2 -0
- package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
- package/dist/components/sidebar/copyable-data-block.js +17 -16
- package/dist/components/sidebar/entity-detail-panel.d.ts +11 -11
- package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
- package/dist/components/sidebar/entity-detail-panel.js +35 -69
- package/dist/components/sidebar/events-list.d.ts +6 -2
- package/dist/components/sidebar/events-list.d.ts.map +1 -1
- package/dist/components/sidebar/events-list.js +76 -62
- package/dist/components/sidebar/resolve-hook-modal.js +1 -1
- package/dist/components/sidebar/sidebar-data-context.d.ts +10 -7
- package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -1
- package/dist/components/sidebar/sidebar-data-context.js +1 -1
- package/dist/components/sidebar/span-detail-merge.d.ts +31 -0
- package/dist/components/sidebar/span-detail-merge.d.ts.map +1 -0
- package/dist/components/sidebar/span-detail-merge.js +92 -0
- package/dist/components/sidebar/use-selected-span-detail.d.ts +16 -0
- package/dist/components/sidebar/use-selected-span-detail.d.ts.map +1 -0
- package/dist/components/sidebar/use-selected-span-detail.js +93 -0
- package/dist/components/stream-viewer.js +1 -1
- package/dist/components/trace-viewer/components/map.d.ts +2 -2
- package/dist/components/trace-viewer/components/map.d.ts.map +1 -1
- package/dist/components/trace-viewer/components/map.js +1 -1
- package/dist/components/trace-viewer/components/markers.js +1 -1
- package/dist/components/trace-viewer/components/node.d.ts +7 -7
- package/dist/components/trace-viewer/components/node.d.ts.map +1 -1
- package/dist/components/trace-viewer/components/node.js +2 -1
- package/dist/components/trace-viewer/components/search-input.js +1 -1
- package/dist/components/trace-viewer/components/search.js +1 -1
- package/dist/components/trace-viewer/components/span-content.js +1 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js +1 -1
- package/dist/components/trace-viewer/components/span-segments.js +1 -1
- package/dist/components/trace-viewer/components/span-strategies.js +1 -1
- package/dist/components/trace-viewer/components/ui.js +1 -1
- package/dist/components/trace-viewer/components/zoom-button.js +1 -1
- package/dist/components/trace-viewer/components/zoom-icons.js +1 -1
- package/dist/components/trace-viewer/context.js +1 -1
- package/dist/components/trace-viewer/index.js +1 -1
- package/dist/components/trace-viewer/trace-viewer.js +1 -1
- package/dist/components/trace-viewer/trace-viewer.module.css +4 -4
- package/dist/components/trace-viewer/types.js +1 -1
- package/dist/components/trace-viewer/util/constants.js +1 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts +3 -3
- package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
- package/dist/components/trace-viewer/util/timing.js +8 -11
- package/dist/components/trace-viewer/util/tree.js +1 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js +1 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js +1 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js +1 -1
- package/dist/components/trace-viewer/worker.js +1 -1
- package/dist/components/trace-viewer-new.d.ts +5 -1
- package/dist/components/trace-viewer-new.d.ts.map +1 -1
- package/dist/components/trace-viewer-new.js +8 -10
- package/dist/components/ui/alert.js +2 -2
- package/dist/components/ui/button.d.ts +10 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +46 -0
- package/dist/components/ui/card.js +2 -2
- package/dist/components/ui/collapsible.d.ts +46 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/collapsible.js +66 -0
- package/dist/components/ui/context-card.d.ts +47 -0
- package/dist/components/ui/context-card.d.ts.map +1 -0
- package/dist/components/ui/context-card.js +471 -0
- package/dist/components/ui/data-inspector.d.ts +7 -6
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +232 -99
- package/dist/components/ui/data-inspector.styles.d.ts +29 -0
- package/dist/components/ui/data-inspector.styles.d.ts.map +1 -0
- package/dist/components/ui/data-inspector.styles.js +95 -0
- package/dist/components/ui/decrypt-button.js +1 -1
- package/dist/components/ui/error-card.js +2 -2
- package/dist/components/ui/error-stack-block.d.ts +17 -10
- package/dist/components/ui/error-stack-block.d.ts.map +1 -1
- package/dist/components/ui/error-stack-block.js +49 -30
- package/dist/components/ui/icon-button.d.ts +19 -0
- package/dist/components/ui/icon-button.d.ts.map +1 -0
- package/dist/components/ui/icon-button.js +29 -0
- package/dist/components/ui/kbd.d.ts +10 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/kbd.js +25 -0
- package/dist/components/ui/load-more-button.js +1 -1
- package/dist/components/ui/menu-dropdown.js +1 -1
- package/dist/components/ui/skeleton.js +2 -2
- package/dist/components/ui/spinner.js +1 -1
- package/dist/components/ui/timestamp-tooltip.d.ts +34 -1
- package/dist/components/ui/timestamp-tooltip.d.ts.map +1 -1
- package/dist/components/ui/timestamp-tooltip.js +80 -132
- package/dist/components/ui/tooltip.d.ts +10 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +12 -0
- package/dist/components/workflow-trace-view.d.ts +7 -8
- package/dist/components/workflow-trace-view.d.ts.map +1 -1
- package/dist/components/workflow-trace-view.js +11 -16
- package/dist/components/workflow-traces/event-colors.d.ts +2 -1
- package/dist/components/workflow-traces/event-colors.d.ts.map +1 -1
- package/dist/components/workflow-traces/event-colors.js +15 -7
- package/dist/components/workflow-traces/trace-colors.d.ts.map +1 -1
- package/dist/components/workflow-traces/trace-colors.js +3 -4
- package/dist/components/workflow-traces/trace-span-construction.d.ts +7 -4
- package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +87 -33
- package/dist/components/workflow-traces/trace-time-utils.js +1 -1
- package/dist/hooks/use-dark-mode.js +1 -1
- package/dist/hooks/use-intersection-observer.d.ts +17 -0
- package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
- package/dist/hooks/use-intersection-observer.js +29 -0
- package/dist/hooks/use-load-more-on-scroll.d.ts +21 -0
- package/dist/hooks/use-load-more-on-scroll.d.ts.map +1 -0
- package/dist/hooks/use-load-more-on-scroll.js +28 -0
- package/dist/hooks/use-reduced-motion.d.ts +10 -0
- package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
- package/dist/hooks/use-reduced-motion.js +29 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/lib/cn.d.ts +10 -0
- package/dist/lib/cn.d.ts.map +1 -0
- package/dist/lib/cn.js +83 -0
- package/dist/lib/event-analysis.d.ts +1 -1
- package/dist/lib/event-analysis.d.ts.map +1 -1
- package/dist/lib/event-analysis.js +3 -2
- package/dist/lib/event-materialization.d.ts +1 -1
- package/dist/lib/event-materialization.d.ts.map +1 -1
- package/dist/lib/event-materialization.js +29 -21
- package/dist/lib/exact-event-search-id.d.ts +25 -0
- package/dist/lib/exact-event-search-id.d.ts.map +1 -0
- package/dist/lib/exact-event-search-id.js +39 -0
- package/dist/lib/hydration.d.ts +17 -2
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +185 -22
- package/dist/lib/stream-display.js +1 -1
- package/dist/lib/toast.js +1 -1
- package/dist/lib/trace-builder.d.ts +16 -4
- package/dist/lib/trace-builder.d.ts.map +1 -1
- package/dist/lib/trace-builder.js +34 -15
- package/dist/lib/utils.d.ts +23 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +73 -33
- package/dist/lib/zstd-browser-decoder.d.ts +7 -0
- package/dist/lib/zstd-browser-decoder.d.ts.map +1 -0
- package/dist/lib/zstd-browser-decoder.js +41 -0
- package/dist/styles.css +14 -0
- package/package.json +10 -7
- package/src/components/event-list-view.tsx +375 -116
- package/src/components/index.ts +12 -5
- package/src/components/new-trace-viewer/components/copy-button.tsx +2 -2
- package/src/components/new-trace-viewer/components/detail-panel-width.test.ts +123 -0
- package/src/components/new-trace-viewer/components/detail-panel-width.ts +76 -0
- package/src/components/new-trace-viewer/components/detail-panel.tsx +273 -0
- package/src/components/new-trace-viewer/components/draggable-border.tsx +216 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +57 -32
- package/src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts +114 -0
- package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +157 -0
- package/src/components/new-trace-viewer/components/middle-truncate/truncate.ts +132 -0
- package/src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts +167 -0
- package/src/components/new-trace-viewer/components/minimap.tsx +559 -0
- package/src/components/new-trace-viewer/components/pane-constants.ts +19 -0
- package/src/components/new-trace-viewer/components/span-markers.tsx +173 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +80 -135
- package/src/components/new-trace-viewer/components/timeline.module.css +46 -0
- package/src/components/new-trace-viewer/components/timeline.tsx +603 -239
- package/src/components/new-trace-viewer/components/trace-shortcut-helper.module.css +20 -0
- package/src/components/new-trace-viewer/components/trace-shortcut-helper.tsx +116 -0
- package/src/components/new-trace-viewer/components/trace-viewer-skeleton.tsx +114 -0
- package/src/components/new-trace-viewer/components/use-element-width.ts +29 -0
- package/src/components/new-trace-viewer/components/use-row-window.ts +140 -0
- package/src/components/new-trace-viewer/context.tsx +13 -14
- package/src/components/new-trace-viewer/icons.tsx +2 -2
- package/src/components/new-trace-viewer/search.ts +178 -0
- package/src/components/new-trace-viewer/trace-viewer.tsx +336 -293
- package/src/components/new-trace-viewer/types.ts +2 -0
- package/src/components/new-trace-viewer/utils.test.ts +247 -0
- package/src/components/new-trace-viewer/utils.ts +203 -134
- package/src/components/run-trace-view.tsx +10 -14
- package/src/components/sidebar/attribute-panel.tsx +276 -275
- package/src/components/sidebar/attributes-block.tsx +326 -0
- package/src/components/sidebar/copyable-data-block.tsx +50 -28
- package/src/components/sidebar/entity-detail-panel.tsx +89 -123
- package/src/components/sidebar/events-list.tsx +196 -178
- package/src/components/sidebar/sidebar-data-context.tsx +11 -11
- package/src/components/sidebar/span-detail-merge.ts +134 -0
- package/src/components/sidebar/use-selected-span-detail.ts +146 -0
- package/src/components/trace-viewer/components/node.tsx +3 -2
- package/src/components/trace-viewer/trace-viewer.module.css +4 -4
- package/src/components/trace-viewer/util/timing.ts +7 -11
- package/src/components/trace-viewer-new.tsx +21 -15
- package/src/components/ui/alert.tsx +1 -1
- package/src/components/ui/button.tsx +68 -0
- package/src/components/ui/card.tsx +1 -1
- package/src/components/ui/collapsible.tsx +219 -0
- package/src/components/ui/context-card.tsx +784 -0
- package/src/components/ui/data-inspector.styles.ts +96 -0
- package/src/components/ui/data-inspector.tsx +501 -204
- package/src/components/ui/error-card.tsx +1 -1
- package/src/components/ui/error-stack-block.tsx +84 -55
- package/src/components/ui/icon-button.tsx +53 -0
- package/src/components/ui/kbd.tsx +43 -0
- package/src/components/ui/skeleton.tsx +1 -1
- package/src/components/ui/timestamp-tooltip.tsx +132 -194
- package/src/components/ui/tooltip.tsx +47 -0
- package/src/components/workflow-trace-view.tsx +31 -36
- package/src/components/workflow-traces/event-colors.ts +15 -11
- package/src/components/workflow-traces/trace-colors.ts +6 -6
- package/src/components/workflow-traces/trace-span-construction.test.ts +85 -0
- package/src/components/workflow-traces/trace-span-construction.ts +118 -35
- package/src/hooks/use-intersection-observer.ts +57 -0
- package/src/hooks/use-load-more-on-scroll.ts +49 -0
- package/src/hooks/use-reduced-motion.ts +34 -0
- package/src/index.ts +9 -0
- package/src/lib/cn.ts +93 -0
- package/src/lib/event-analysis.ts +6 -4
- package/src/lib/event-materialization.ts +35 -21
- package/src/lib/exact-event-search-id.ts +67 -0
- package/src/lib/hydration.ts +203 -29
- package/src/lib/trace-builder.ts +44 -19
- package/src/lib/utils.test.ts +33 -0
- package/src/lib/utils.ts +82 -35
- package/src/lib/zstd-browser-decoder.ts +42 -0
- package/src/styles.css +14 -0
- package/dist/components/error-boundary.js.map +0 -1
- package/dist/components/event-list-view.js.map +0 -1
- package/dist/components/hook-actions.js.map +0 -1
- package/dist/components/index.js.map +0 -1
- package/dist/components/new-trace-viewer/components/copy-button.js.map +0 -1
- package/dist/components/new-trace-viewer/components/event-list.js.map +0 -1
- package/dist/components/new-trace-viewer/components/split-pane.js.map +0 -1
- package/dist/components/new-trace-viewer/components/timeline.js.map +0 -1
- package/dist/components/new-trace-viewer/context.js.map +0 -1
- package/dist/components/new-trace-viewer/detail-panel.d.ts +0 -10
- package/dist/components/new-trace-viewer/detail-panel.d.ts.map +0 -1
- package/dist/components/new-trace-viewer/detail-panel.js +0 -11
- package/dist/components/new-trace-viewer/detail-panel.js.map +0 -1
- package/dist/components/new-trace-viewer/icons.js.map +0 -1
- package/dist/components/new-trace-viewer/trace-viewer.js.map +0 -1
- package/dist/components/new-trace-viewer/types.js.map +0 -1
- package/dist/components/new-trace-viewer/util/constants.d.ts +0 -1
- package/dist/components/new-trace-viewer/util/constants.d.ts.map +0 -1
- package/dist/components/new-trace-viewer/util/constants.js +0 -2
- package/dist/components/new-trace-viewer/util/constants.js.map +0 -1
- package/dist/components/new-trace-viewer/utils.js.map +0 -1
- package/dist/components/run-trace-view.js.map +0 -1
- package/dist/components/sidebar/attribute-panel.js.map +0 -1
- package/dist/components/sidebar/conversation-view.js.map +0 -1
- package/dist/components/sidebar/copyable-data-block.js.map +0 -1
- package/dist/components/sidebar/detail-card.d.ts +0 -14
- package/dist/components/sidebar/detail-card.d.ts.map +0 -1
- package/dist/components/sidebar/detail-card.js +0 -20
- package/dist/components/sidebar/detail-card.js.map +0 -1
- package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
- package/dist/components/sidebar/events-list.js.map +0 -1
- package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
- package/dist/components/sidebar/sidebar-data-context.js.map +0 -1
- package/dist/components/stream-viewer.js.map +0 -1
- package/dist/components/trace-viewer/components/map.js.map +0 -1
- package/dist/components/trace-viewer/components/markers.js.map +0 -1
- package/dist/components/trace-viewer/components/node.js.map +0 -1
- package/dist/components/trace-viewer/components/search-input.js.map +0 -1
- package/dist/components/trace-viewer/components/search.js.map +0 -1
- package/dist/components/trace-viewer/components/span-content.js.map +0 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
- package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
- package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
- package/dist/components/trace-viewer/components/ui.js.map +0 -1
- package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
- package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
- package/dist/components/trace-viewer/context.js.map +0 -1
- package/dist/components/trace-viewer/index.js.map +0 -1
- package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
- package/dist/components/trace-viewer/types.js.map +0 -1
- package/dist/components/trace-viewer/util/constants.js.map +0 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
- package/dist/components/trace-viewer/util/timing.js.map +0 -1
- package/dist/components/trace-viewer/util/tree.js.map +0 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
- package/dist/components/trace-viewer/worker.js.map +0 -1
- package/dist/components/trace-viewer-new.js.map +0 -1
- package/dist/components/ui/alert.js.map +0 -1
- package/dist/components/ui/card.js.map +0 -1
- package/dist/components/ui/data-inspector.js.map +0 -1
- package/dist/components/ui/decrypt-button.js.map +0 -1
- package/dist/components/ui/error-card.js.map +0 -1
- package/dist/components/ui/error-stack-block.js.map +0 -1
- package/dist/components/ui/inspector-theme.d.ts +0 -95
- package/dist/components/ui/inspector-theme.d.ts.map +0 -1
- package/dist/components/ui/inspector-theme.js +0 -82
- package/dist/components/ui/inspector-theme.js.map +0 -1
- package/dist/components/ui/load-more-button.js.map +0 -1
- package/dist/components/ui/menu-dropdown.js.map +0 -1
- package/dist/components/ui/skeleton.js.map +0 -1
- package/dist/components/ui/spinner.js.map +0 -1
- package/dist/components/ui/timestamp-tooltip.js.map +0 -1
- package/dist/components/workflow-trace-view.js.map +0 -1
- package/dist/components/workflow-traces/event-colors.js.map +0 -1
- package/dist/components/workflow-traces/trace-colors.js.map +0 -1
- package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
- package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
- package/dist/hooks/use-dark-mode.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/event-analysis.js.map +0 -1
- package/dist/lib/event-materialization.js.map +0 -1
- package/dist/lib/hydration.js.map +0 -1
- package/dist/lib/stream-display.js.map +0 -1
- package/dist/lib/toast.js.map +0 -1
- package/dist/lib/trace-builder.js.map +0 -1
- package/dist/lib/utils.js.map +0 -1
- package/src/components/new-trace-viewer/detail-panel.tsx +0 -57
- package/src/components/new-trace-viewer/util/constants.ts +0 -0
- package/src/components/sidebar/detail-card.tsx +0 -65
- package/src/components/ui/inspector-theme.ts +0 -110
|
@@ -1,53 +1,70 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { Search, X } from 'lucide-react';
|
|
3
|
+
import { RotateCcw, Search, ZoomIn, ZoomOut } from 'lucide-react';
|
|
5
4
|
import {
|
|
6
5
|
type ReactNode,
|
|
7
6
|
useCallback,
|
|
7
|
+
useDeferredValue,
|
|
8
8
|
useEffect,
|
|
9
9
|
useMemo,
|
|
10
10
|
useRef,
|
|
11
11
|
useState,
|
|
12
12
|
} from 'react';
|
|
13
|
-
import {
|
|
13
|
+
import { useLoadMoreOnScroll } from '../../hooks/use-load-more-on-scroll';
|
|
14
|
+
import { useReducedMotion } from '../../hooks/use-reduced-motion';
|
|
14
15
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from '../
|
|
18
|
-
import {
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
16
|
+
formatDurationPrecise,
|
|
17
|
+
getHighResInMs,
|
|
18
|
+
} from '../trace-viewer/util/timing';
|
|
19
|
+
import { IconButton } from '../ui/icon-button';
|
|
20
|
+
import { Kbd } from '../ui/kbd';
|
|
21
|
+
import { Spinner } from '../ui/spinner';
|
|
22
|
+
import { TooltipProvider } from '../ui/tooltip';
|
|
23
|
+
import { TraceDetailPanel } from './components/detail-panel';
|
|
23
24
|
import EventList from './components/event-list';
|
|
24
|
-
import {
|
|
25
|
+
import { Minimap } from './components/minimap';
|
|
26
|
+
import { SplitPane } from './components/split-pane';
|
|
27
|
+
import {
|
|
28
|
+
TIMELINE_PADDING_PX,
|
|
29
|
+
Timeline,
|
|
30
|
+
TimelineHeader,
|
|
31
|
+
} from './components/timeline';
|
|
32
|
+
import { TraceShortcutHelper } from './components/trace-shortcut-helper';
|
|
33
|
+
import { ROW_HEIGHT_PX, scrollRowIntoView } from './components/use-row-window';
|
|
25
34
|
import { ActiveSpanProvider, useActiveSpan } from './context';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
35
|
+
import { searchSpans } from './search';
|
|
36
|
+
import type { TraceWithMeta } from './types';
|
|
37
|
+
import {
|
|
38
|
+
clampViewportToRoot,
|
|
39
|
+
computeRootBounds,
|
|
40
|
+
computeTimeMarkers,
|
|
41
|
+
type ViewportRange,
|
|
42
|
+
wheelDeltaToPixels,
|
|
43
|
+
wheelZoomScaleFactor,
|
|
44
|
+
} from './utils';
|
|
28
45
|
|
|
29
46
|
interface NewTraceViewerProps {
|
|
30
|
-
trace:
|
|
47
|
+
trace: TraceWithMeta;
|
|
48
|
+
onLoadMore?: () => void | Promise<void>;
|
|
49
|
+
hasMore?: boolean;
|
|
50
|
+
isLoadingMore?: boolean;
|
|
31
51
|
}
|
|
32
52
|
|
|
33
53
|
const MIN_VIEWPORT_MS = 0.001;
|
|
34
|
-
const TIMELINE_PADDING = 16;
|
|
35
54
|
|
|
36
|
-
|
|
37
|
-
start: number;
|
|
38
|
-
end: number;
|
|
39
|
-
}
|
|
55
|
+
const ZOOM_DEBOUNCE_MS = 150;
|
|
40
56
|
|
|
41
|
-
function useAnimatedViewport(initial:
|
|
42
|
-
const [viewport, setViewportState] = useState<
|
|
57
|
+
function useAnimatedViewport(initial: ViewportRange) {
|
|
58
|
+
const [viewport, setViewportState] = useState<ViewportRange>(initial);
|
|
43
59
|
const animRef = useRef<{
|
|
44
60
|
raf: number;
|
|
45
|
-
from:
|
|
46
|
-
to:
|
|
61
|
+
from: ViewportRange;
|
|
62
|
+
to: ViewportRange;
|
|
47
63
|
start: number;
|
|
48
64
|
} | null>(null);
|
|
49
65
|
const currentRef = useRef(initial);
|
|
50
66
|
currentRef.current = viewport;
|
|
67
|
+
const reducedMotion = useReducedMotion();
|
|
51
68
|
|
|
52
69
|
const cancel = useCallback(() => {
|
|
53
70
|
if (animRef.current) {
|
|
@@ -57,14 +74,21 @@ function useAnimatedViewport(initial: Viewport) {
|
|
|
57
74
|
}, []);
|
|
58
75
|
|
|
59
76
|
const animateTo = useCallback(
|
|
60
|
-
(target:
|
|
77
|
+
(target: ViewportRange) => {
|
|
61
78
|
cancel();
|
|
79
|
+
|
|
80
|
+
if (reducedMotion) {
|
|
81
|
+
currentRef.current = target;
|
|
82
|
+
setViewportState(target);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
62
86
|
const from = currentRef.current;
|
|
63
87
|
const anim = { raf: 0, from, to: target, start: performance.now() };
|
|
64
88
|
|
|
65
89
|
const tick = () => {
|
|
66
|
-
const t = Math.min((performance.now() - anim.start) /
|
|
67
|
-
const e =
|
|
90
|
+
const t = Math.min((performance.now() - anim.start) / 240, 1);
|
|
91
|
+
const e = t < 0.5 ? 8 * t * t * t * t : 1 - (-2 * t + 2) ** 4 / 2;
|
|
68
92
|
setViewportState({
|
|
69
93
|
start: anim.from.start + (anim.to.start - anim.from.start) * e,
|
|
70
94
|
end: anim.from.end + (anim.to.end - anim.from.end) * e,
|
|
@@ -76,11 +100,11 @@ function useAnimatedViewport(initial: Viewport) {
|
|
|
76
100
|
animRef.current = anim;
|
|
77
101
|
anim.raf = requestAnimationFrame(tick);
|
|
78
102
|
},
|
|
79
|
-
[cancel]
|
|
103
|
+
[cancel, reducedMotion]
|
|
80
104
|
);
|
|
81
105
|
|
|
82
106
|
const setViewport = useCallback(
|
|
83
|
-
(update:
|
|
107
|
+
(update: ViewportRange | ((prev: ViewportRange) => ViewportRange)) => {
|
|
84
108
|
cancel();
|
|
85
109
|
if (typeof update === 'function') {
|
|
86
110
|
setViewportState((prev) => {
|
|
@@ -101,69 +125,68 @@ function useAnimatedViewport(initial: Viewport) {
|
|
|
101
125
|
return { viewport, setViewport, animateTo };
|
|
102
126
|
}
|
|
103
127
|
|
|
104
|
-
// ---------------------------------------------------------------------------
|
|
105
|
-
// Hook: bridge ActiveSpanContext + SidebarDataContext → SelectedSpanInfo
|
|
106
|
-
// ---------------------------------------------------------------------------
|
|
107
|
-
|
|
108
|
-
function useSelectedSpanInfo(): SelectedSpanInfo | null {
|
|
109
|
-
const { activeSpan } = useActiveSpan();
|
|
110
|
-
const sidebar = useSidebarDataOptional();
|
|
111
|
-
|
|
112
|
-
return useMemo(() => {
|
|
113
|
-
if (!activeSpan || !sidebar) return null;
|
|
114
|
-
|
|
115
|
-
const correlationId = activeSpan.spanId;
|
|
116
|
-
const rawEvents = correlationId
|
|
117
|
-
? sidebar.events.filter((e) => e.correlationId === correlationId)
|
|
118
|
-
: [];
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
data: activeSpan.attributes?.data,
|
|
122
|
-
resource: activeSpan.attributes?.resource as string | undefined,
|
|
123
|
-
spanId: activeSpan.spanId,
|
|
124
|
-
rawEvents,
|
|
125
|
-
};
|
|
126
|
-
}, [activeSpan, sidebar?.events]);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
128
|
// ---------------------------------------------------------------------------
|
|
130
129
|
// Root component
|
|
131
130
|
// ---------------------------------------------------------------------------
|
|
132
131
|
|
|
133
|
-
export function NewTraceViewer({
|
|
132
|
+
export function NewTraceViewer({
|
|
133
|
+
trace,
|
|
134
|
+
onLoadMore,
|
|
135
|
+
hasMore,
|
|
136
|
+
isLoadingMore,
|
|
137
|
+
}: NewTraceViewerProps): ReactNode {
|
|
134
138
|
return (
|
|
135
|
-
<
|
|
136
|
-
<
|
|
137
|
-
|
|
139
|
+
<TooltipProvider delayDuration={300}>
|
|
140
|
+
<ActiveSpanProvider spans={trace.spans}>
|
|
141
|
+
<NewTraceViewerContent
|
|
142
|
+
trace={trace}
|
|
143
|
+
onLoadMore={onLoadMore}
|
|
144
|
+
hasMore={hasMore}
|
|
145
|
+
isLoadingMore={isLoadingMore}
|
|
146
|
+
/>
|
|
147
|
+
</ActiveSpanProvider>
|
|
148
|
+
</TooltipProvider>
|
|
138
149
|
);
|
|
139
150
|
}
|
|
140
151
|
|
|
141
|
-
function NewTraceViewerContent({
|
|
142
|
-
|
|
143
|
-
|
|
152
|
+
function NewTraceViewerContent({
|
|
153
|
+
trace,
|
|
154
|
+
onLoadMore,
|
|
155
|
+
hasMore,
|
|
156
|
+
isLoadingMore,
|
|
157
|
+
}: NewTraceViewerProps): ReactNode {
|
|
158
|
+
const { activeSpanId, setActiveSpan, clearActiveSpan } = useActiveSpan();
|
|
144
159
|
|
|
145
|
-
const
|
|
146
|
-
const selectedSpan = useSelectedSpanInfo();
|
|
160
|
+
const reducedMotion = useReducedMotion();
|
|
147
161
|
|
|
148
162
|
const [searchQuery, setSearchQuery] = useState('');
|
|
163
|
+
const deferredSearchQuery = useDeferredValue(searchQuery);
|
|
164
|
+
|
|
165
|
+
const paneRootRef = useRef<HTMLDivElement>(null);
|
|
149
166
|
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
(s) =>
|
|
155
|
-
s.name.toLowerCase().includes(q) || s.resource.toLowerCase().includes(q)
|
|
156
|
-
);
|
|
157
|
-
}, [trace.spans, searchQuery]);
|
|
167
|
+
const searchResult = useMemo(
|
|
168
|
+
() => searchSpans(trace.spans, deferredSearchQuery),
|
|
169
|
+
[trace.spans, deferredSearchQuery]
|
|
170
|
+
);
|
|
158
171
|
|
|
159
172
|
const root = useMemo(() => computeRootBounds(trace.spans), [trace.spans]);
|
|
160
173
|
|
|
174
|
+
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
|
175
|
+
const loadMore = useCallback(() => {
|
|
176
|
+
void onLoadMore?.();
|
|
177
|
+
}, [onLoadMore]);
|
|
178
|
+
const loadMoreSentinelRef = useLoadMoreOnScroll(loadMore, {
|
|
179
|
+
hasMore: Boolean(onLoadMore && hasMore),
|
|
180
|
+
isLoadingMore: Boolean(isLoadingMore),
|
|
181
|
+
rootRef: scrollContainerRef,
|
|
182
|
+
});
|
|
183
|
+
|
|
161
184
|
const { viewport, setViewport, animateTo } = useAnimatedViewport({
|
|
162
185
|
start: root.startTime,
|
|
163
186
|
end: root.startTime + root.duration,
|
|
164
187
|
});
|
|
165
188
|
|
|
166
|
-
const prevRootRef = useRef<
|
|
189
|
+
const prevRootRef = useRef<ViewportRange>({
|
|
167
190
|
start: root.startTime,
|
|
168
191
|
end: root.startTime + root.duration,
|
|
169
192
|
});
|
|
@@ -185,31 +208,73 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
|
|
|
185
208
|
});
|
|
186
209
|
|
|
187
210
|
prevRootRef.current = { start: newStart, end: newEnd };
|
|
188
|
-
}, [root.startTime, root.duration]);
|
|
211
|
+
}, [root.startTime, root.duration, setViewport]);
|
|
189
212
|
|
|
190
213
|
const viewDuration = viewport.end - viewport.start;
|
|
191
214
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
);
|
|
215
|
+
// Keep a ref to the live viewport so the reveal callback can read the current
|
|
216
|
+
// zoom without being recreated on every pan (which would bust TimelineBar's
|
|
217
|
+
// memo and re-render every row each animation frame).
|
|
218
|
+
const viewportRef = useRef(viewport);
|
|
219
|
+
viewportRef.current = viewport;
|
|
196
220
|
|
|
197
|
-
const
|
|
198
|
-
viewport.start
|
|
199
|
-
viewport.
|
|
221
|
+
const timeMarkers = useMemo(
|
|
222
|
+
() => computeTimeMarkers(viewDuration, viewport.start - root.startTime),
|
|
223
|
+
[viewDuration, viewport.start, root.startTime]
|
|
224
|
+
);
|
|
200
225
|
|
|
201
226
|
const resetZoom = useCallback(() => {
|
|
202
227
|
animateTo({ start: root.startTime, end: root.startTime + root.duration });
|
|
203
228
|
}, [animateTo, root.startTime, root.duration]);
|
|
204
229
|
|
|
205
|
-
const
|
|
206
|
-
(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
230
|
+
const clampToRoot = useCallback(
|
|
231
|
+
(next: ViewportRange): ViewportRange =>
|
|
232
|
+
clampViewportToRoot(next, root.startTime, root.endTime, MIN_VIEWPORT_MS),
|
|
233
|
+
[root.startTime, root.endTime]
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
// Pan (keeping the current zoom) so `timeMs` is centered in view — used by the
|
|
237
|
+
// off-screen marker indicators to scroll their marker into view.
|
|
238
|
+
const handleRevealTime = useCallback(
|
|
239
|
+
(timeMs: number) => {
|
|
240
|
+
const { start, end } = viewportRef.current;
|
|
241
|
+
const duration = end - start;
|
|
242
|
+
animateTo(
|
|
243
|
+
clampToRoot({
|
|
244
|
+
start: timeMs - duration / 2,
|
|
245
|
+
end: timeMs + duration / 2,
|
|
246
|
+
})
|
|
247
|
+
);
|
|
248
|
+
},
|
|
249
|
+
[animateTo, clampToRoot]
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
const ZOOM_FACTOR = 0.5;
|
|
253
|
+
|
|
254
|
+
const zoomBy = useCallback(
|
|
255
|
+
(factor: number) => {
|
|
256
|
+
setViewport((prev) => {
|
|
257
|
+
const center = (prev.start + prev.end) / 2;
|
|
258
|
+
const newDuration = Math.max(
|
|
259
|
+
MIN_VIEWPORT_MS,
|
|
260
|
+
(prev.end - prev.start) * factor
|
|
261
|
+
);
|
|
262
|
+
return clampToRoot({
|
|
263
|
+
start: center - newDuration / 2,
|
|
264
|
+
end: center + newDuration / 2,
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
},
|
|
268
|
+
[setViewport, clampToRoot]
|
|
269
|
+
);
|
|
212
270
|
|
|
271
|
+
const zoomIn = useCallback(() => zoomBy(ZOOM_FACTOR), [zoomBy]);
|
|
272
|
+
const zoomOut = useCallback(() => zoomBy(1 / ZOOM_FACTOR), [zoomBy]);
|
|
273
|
+
const isAtMinZoom = viewDuration >= root.duration;
|
|
274
|
+
const isAtMaxZoom = viewDuration <= MIN_VIEWPORT_MS;
|
|
275
|
+
|
|
276
|
+
const focusViewportOnSpan = useCallback(
|
|
277
|
+
(spanId: string) => {
|
|
213
278
|
const span = trace.spans.find((s) => s.spanId === spanId);
|
|
214
279
|
if (!span) return;
|
|
215
280
|
|
|
@@ -217,12 +282,8 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
|
|
|
217
282
|
const spanEnd = getHighResInMs(span.endTime);
|
|
218
283
|
const spanDuration = spanEnd - spanStart;
|
|
219
284
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const rootD = root.duration;
|
|
223
|
-
|
|
224
|
-
if (spanDuration > rootD * 0.8) {
|
|
225
|
-
animateTo({ start: rootS, end: rootE });
|
|
285
|
+
if (spanDuration > root.duration * 0.8) {
|
|
286
|
+
animateTo({ start: root.startTime, end: root.endTime });
|
|
226
287
|
return;
|
|
227
288
|
}
|
|
228
289
|
|
|
@@ -236,39 +297,90 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
|
|
|
236
297
|
newEnd = center + MIN_VIEWPORT_MS / 2;
|
|
237
298
|
}
|
|
238
299
|
|
|
239
|
-
|
|
240
|
-
const duration = newEnd - newStart;
|
|
241
|
-
newStart = rootS;
|
|
242
|
-
newEnd = Math.min(rootE, rootS + duration);
|
|
243
|
-
}
|
|
244
|
-
if (newEnd > rootE) {
|
|
245
|
-
const duration = newEnd - newStart;
|
|
246
|
-
newEnd = rootE;
|
|
247
|
-
newStart = Math.max(rootS, rootE - duration);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
animateTo({ start: newStart, end: newEnd });
|
|
300
|
+
animateTo(clampToRoot({ start: newStart, end: newEnd }));
|
|
251
301
|
},
|
|
252
302
|
[
|
|
253
303
|
animateTo,
|
|
254
|
-
setActiveSpan,
|
|
255
|
-
clearActiveSpan,
|
|
256
|
-
activeSpanId,
|
|
257
304
|
trace.spans,
|
|
258
305
|
root.startTime,
|
|
306
|
+
root.endTime,
|
|
259
307
|
root.duration,
|
|
308
|
+
clampToRoot,
|
|
260
309
|
]
|
|
261
310
|
);
|
|
262
311
|
|
|
312
|
+
// Bring a row into view when keyboard/button navigation lands on a span that
|
|
313
|
+
// sits outside the shared scroll container's visible area. The list is
|
|
314
|
+
// windowed, so an off-screen row has no DOM node to `scrollIntoView` —
|
|
315
|
+
// `scrollRowIntoView` computes the target offset from the span's index.
|
|
316
|
+
const scrollSpanIntoView = useCallback(
|
|
317
|
+
(spanId: string) => {
|
|
318
|
+
const index = trace.spans.findIndex((s) => s.spanId === spanId);
|
|
319
|
+
if (index === -1) return;
|
|
320
|
+
|
|
321
|
+
const list =
|
|
322
|
+
scrollContainerRef.current?.querySelector<HTMLElement>('#event-list') ??
|
|
323
|
+
null;
|
|
324
|
+
scrollRowIntoView(list, index, ROW_HEIGHT_PX, {
|
|
325
|
+
behavior: reducedMotion ? 'auto' : 'smooth',
|
|
326
|
+
});
|
|
327
|
+
},
|
|
328
|
+
[trace.spans, reducedMotion]
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
const zoomTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
332
|
+
const cancelPendingZoom = useCallback(() => {
|
|
333
|
+
if (zoomTimerRef.current !== null) {
|
|
334
|
+
clearTimeout(zoomTimerRef.current);
|
|
335
|
+
zoomTimerRef.current = null;
|
|
336
|
+
}
|
|
337
|
+
}, []);
|
|
338
|
+
useEffect(() => cancelPendingZoom, [cancelPendingZoom]);
|
|
339
|
+
|
|
340
|
+
const handleClearActiveSpan = useCallback(() => {
|
|
341
|
+
cancelPendingZoom();
|
|
342
|
+
clearActiveSpan();
|
|
343
|
+
}, [cancelPendingZoom, clearActiveSpan]);
|
|
344
|
+
|
|
345
|
+
const handleSelectSpan = useCallback(
|
|
346
|
+
(spanId: string) => {
|
|
347
|
+
cancelPendingZoom();
|
|
348
|
+
if (spanId === activeSpanId) {
|
|
349
|
+
clearActiveSpan();
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
setActiveSpan(spanId);
|
|
353
|
+
focusViewportOnSpan(spanId);
|
|
354
|
+
},
|
|
355
|
+
[
|
|
356
|
+
cancelPendingZoom,
|
|
357
|
+
activeSpanId,
|
|
358
|
+
clearActiveSpan,
|
|
359
|
+
setActiveSpan,
|
|
360
|
+
focusViewportOnSpan,
|
|
361
|
+
]
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
const navigateToSpan = useCallback(
|
|
365
|
+
(spanId: string) => {
|
|
366
|
+
setActiveSpan(spanId);
|
|
367
|
+
scrollSpanIntoView(spanId);
|
|
368
|
+
cancelPendingZoom();
|
|
369
|
+
zoomTimerRef.current = setTimeout(() => {
|
|
370
|
+
zoomTimerRef.current = null;
|
|
371
|
+
focusViewportOnSpan(spanId);
|
|
372
|
+
}, ZOOM_DEBOUNCE_MS);
|
|
373
|
+
},
|
|
374
|
+
[setActiveSpan, scrollSpanIntoView, cancelPendingZoom, focusViewportOnSpan]
|
|
375
|
+
);
|
|
376
|
+
|
|
263
377
|
const [altHeld, setAltHeld] = useState(false);
|
|
264
378
|
|
|
265
379
|
useEffect(() => {
|
|
266
380
|
const onKeyDown = (e: KeyboardEvent): void => {
|
|
267
381
|
if (e.key === 'Escape') {
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
if (e.key === 'Alt') {
|
|
271
|
-
e.preventDefault();
|
|
382
|
+
handleClearActiveSpan();
|
|
383
|
+
} else if (e.key === 'Alt') {
|
|
272
384
|
setAltHeld(true);
|
|
273
385
|
}
|
|
274
386
|
};
|
|
@@ -285,29 +397,31 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
|
|
|
285
397
|
window.removeEventListener('keyup', onKeyUp);
|
|
286
398
|
window.removeEventListener('blur', onBlur);
|
|
287
399
|
};
|
|
288
|
-
}, [
|
|
400
|
+
}, [handleClearActiveSpan]);
|
|
289
401
|
|
|
290
402
|
const timelineRef = useRef<HTMLDivElement>(null);
|
|
291
403
|
const [hoverFraction, setHoverFraction] = useState<number | null>(null);
|
|
292
404
|
|
|
293
405
|
const hoverInfo = useMemo(() => {
|
|
294
406
|
if (hoverFraction == null) return null;
|
|
295
|
-
const absTime =
|
|
407
|
+
const absTime = viewport.start + hoverFraction * viewDuration;
|
|
296
408
|
const offset = absTime - root.startTime;
|
|
297
|
-
return { fraction: hoverFraction, label:
|
|
298
|
-
}, [hoverFraction,
|
|
409
|
+
return { fraction: hoverFraction, label: formatDurationPrecise(offset) };
|
|
410
|
+
}, [hoverFraction, viewport.start, viewDuration, root.startTime]);
|
|
299
411
|
|
|
300
412
|
const handleTimelineMouseMove = useCallback(
|
|
301
413
|
(e: React.MouseEvent<HTMLDivElement>) => {
|
|
302
414
|
const el = timelineRef.current;
|
|
303
415
|
if (!el) return;
|
|
304
416
|
const rect = el.getBoundingClientRect();
|
|
305
|
-
const
|
|
306
|
-
const contentWidth = rect.width - padding * 2;
|
|
417
|
+
const contentWidth = rect.width - TIMELINE_PADDING_PX * 2;
|
|
307
418
|
if (contentWidth <= 0) return;
|
|
308
419
|
const fraction = Math.max(
|
|
309
420
|
0,
|
|
310
|
-
Math.min(
|
|
421
|
+
Math.min(
|
|
422
|
+
1,
|
|
423
|
+
(e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth
|
|
424
|
+
)
|
|
311
425
|
);
|
|
312
426
|
setHoverFraction(fraction);
|
|
313
427
|
},
|
|
@@ -320,12 +434,7 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
|
|
|
320
434
|
|
|
321
435
|
useEffect(() => {
|
|
322
436
|
const el = timelineRef.current;
|
|
323
|
-
if (!el) return;
|
|
324
|
-
|
|
325
|
-
const rootS = root.startTime;
|
|
326
|
-
const rootE = root.startTime + root.duration;
|
|
327
|
-
const rootD = root.duration;
|
|
328
|
-
if (rootD <= 0) return;
|
|
437
|
+
if (!el || root.duration <= 0) return;
|
|
329
438
|
|
|
330
439
|
const onWheel = (e: WheelEvent): void => {
|
|
331
440
|
const isZoomGesture = e.ctrlKey || e.metaKey;
|
|
@@ -335,111 +444,71 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
|
|
|
335
444
|
e.preventDefault();
|
|
336
445
|
|
|
337
446
|
const rect = el.getBoundingClientRect();
|
|
338
|
-
const contentWidth = rect.width -
|
|
447
|
+
const contentWidth = rect.width - TIMELINE_PADDING_PX * 2;
|
|
339
448
|
if (contentWidth <= 0) return;
|
|
340
449
|
|
|
341
450
|
if (isZoomGesture) {
|
|
342
|
-
let dy = e.deltaY;
|
|
343
|
-
if (e.deltaMode === 1) dy *= 16;
|
|
344
|
-
|
|
345
451
|
const cursorFraction = Math.max(
|
|
346
452
|
0,
|
|
347
|
-
Math.min(
|
|
453
|
+
Math.min(
|
|
454
|
+
1,
|
|
455
|
+
(e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth
|
|
456
|
+
)
|
|
348
457
|
);
|
|
349
|
-
const scaleFactor =
|
|
458
|
+
const scaleFactor = wheelZoomScaleFactor(e);
|
|
350
459
|
|
|
351
460
|
setViewport((prev) => {
|
|
352
461
|
const prevDuration = prev.end - prev.start;
|
|
353
462
|
const cursorTime = prev.start + cursorFraction * prevDuration;
|
|
463
|
+
// Clamp the duration before anchoring so the cursor keeps its
|
|
464
|
+
// fraction even when the zoom hits the min/max bounds.
|
|
354
465
|
const newDuration = Math.max(
|
|
355
466
|
MIN_VIEWPORT_MS,
|
|
356
|
-
Math.min(
|
|
467
|
+
Math.min(root.duration, prevDuration * scaleFactor)
|
|
357
468
|
);
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
if (newStart < rootS) {
|
|
363
|
-
newStart = rootS;
|
|
364
|
-
newEnd = rootS + newDuration;
|
|
365
|
-
}
|
|
366
|
-
if (newEnd > rootE) {
|
|
367
|
-
newEnd = rootE;
|
|
368
|
-
newStart = Math.max(rootS, rootE - newDuration);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
return { start: newStart, end: newEnd };
|
|
469
|
+
return clampToRoot({
|
|
470
|
+
start: cursorTime - cursorFraction * newDuration,
|
|
471
|
+
end: cursorTime + (1 - cursorFraction) * newDuration,
|
|
472
|
+
});
|
|
372
473
|
});
|
|
373
474
|
} else {
|
|
374
|
-
|
|
375
|
-
if (e.deltaMode === 1) dx *= 16;
|
|
376
|
-
|
|
475
|
+
const dx = wheelDeltaToPixels(e.deltaX, e.deltaMode);
|
|
377
476
|
setViewport((prev) => {
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
if (newStart < rootS) {
|
|
385
|
-
newStart = rootS;
|
|
386
|
-
newEnd = rootS + prevDuration;
|
|
387
|
-
}
|
|
388
|
-
if (newEnd > rootE) {
|
|
389
|
-
newEnd = rootE;
|
|
390
|
-
newStart = Math.max(rootS, rootE - prevDuration);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
return { start: newStart, end: newEnd };
|
|
477
|
+
const panAmount = (dx / contentWidth) * (prev.end - prev.start);
|
|
478
|
+
return clampToRoot({
|
|
479
|
+
start: prev.start + panAmount,
|
|
480
|
+
end: prev.end + panAmount,
|
|
481
|
+
});
|
|
394
482
|
});
|
|
395
483
|
}
|
|
396
484
|
};
|
|
397
485
|
|
|
398
486
|
el.addEventListener('wheel', onWheel, { passive: false });
|
|
399
487
|
return () => el.removeEventListener('wheel', onWheel);
|
|
400
|
-
}, [root.
|
|
401
|
-
|
|
402
|
-
// Derive the selected span name and metadata for the panel header
|
|
403
|
-
const selectedSpanName = useMemo(() => {
|
|
404
|
-
if (!selectedSpan?.data) return 'Details';
|
|
405
|
-
const data = selectedSpan.data as Record<string, unknown>;
|
|
406
|
-
const stepName = data.stepName as string | undefined;
|
|
407
|
-
const workflowName = data.workflowName as string | undefined;
|
|
408
|
-
return (
|
|
409
|
-
(stepName ? parseStepName(stepName)?.shortName : undefined) ??
|
|
410
|
-
(workflowName ? parseWorkflowName(workflowName)?.shortName : undefined) ??
|
|
411
|
-
stepName ??
|
|
412
|
-
workflowName ??
|
|
413
|
-
(data.hookId as string) ??
|
|
414
|
-
'Details'
|
|
415
|
-
);
|
|
416
|
-
}, [selectedSpan?.data]);
|
|
417
|
-
|
|
418
|
-
const selectedResource = selectedSpan?.resource as string | undefined;
|
|
419
|
-
const selectedResourceId = useMemo(() => {
|
|
420
|
-
if (!selectedSpan?.data) return undefined;
|
|
421
|
-
const data = selectedSpan.data as Record<string, unknown>;
|
|
422
|
-
return (
|
|
423
|
-
(data.stepId as string) ??
|
|
424
|
-
(data.runId as string) ??
|
|
425
|
-
(data.hookId as string) ??
|
|
426
|
-
selectedSpan.spanId
|
|
427
|
-
);
|
|
428
|
-
}, [selectedSpan?.data, selectedSpan?.spanId]);
|
|
488
|
+
}, [root.duration, setViewport, clampToRoot]);
|
|
429
489
|
|
|
430
490
|
return (
|
|
431
491
|
<div
|
|
492
|
+
ref={paneRootRef}
|
|
432
493
|
data-pane="pane-root"
|
|
433
|
-
|
|
434
|
-
className="grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,420px,100%)]"
|
|
494
|
+
className="relative flex w-full h-full max-h-full"
|
|
435
495
|
>
|
|
436
496
|
<div
|
|
437
497
|
id="trace-parent"
|
|
438
|
-
className="grid grid-rows-[
|
|
498
|
+
className="flex-1 min-w-0 grid grid-rows-[auto_1fr] h-full min-h-0 overflow-hidden relative bg-background-100"
|
|
439
499
|
>
|
|
500
|
+
<Minimap
|
|
501
|
+
spans={trace.spans}
|
|
502
|
+
root={root}
|
|
503
|
+
viewport={viewport}
|
|
504
|
+
minViewportMs={MIN_VIEWPORT_MS}
|
|
505
|
+
onViewportChange={setViewport}
|
|
506
|
+
onAnimateTo={animateTo}
|
|
507
|
+
/>
|
|
440
508
|
<SplitPane
|
|
509
|
+
scrollContainerRef={scrollContainerRef}
|
|
441
510
|
startHeader={
|
|
442
|
-
<div className="bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center
|
|
511
|
+
<div className="bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center pl-4 pr-2 gap-1.5">
|
|
443
512
|
<Search className="w-3.5 h-3.5 shrink-0 text-gray-800" />
|
|
444
513
|
<input
|
|
445
514
|
id="trace-viewer-search"
|
|
@@ -447,6 +516,13 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
|
|
|
447
516
|
type="text"
|
|
448
517
|
value={searchQuery}
|
|
449
518
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
519
|
+
onKeyDown={(e) => {
|
|
520
|
+
if (e.key === 'Escape' && searchQuery) {
|
|
521
|
+
e.preventDefault();
|
|
522
|
+
e.stopPropagation();
|
|
523
|
+
setSearchQuery('');
|
|
524
|
+
}
|
|
525
|
+
}}
|
|
450
526
|
placeholder="Search spans..."
|
|
451
527
|
aria-label="Search spans"
|
|
452
528
|
className="flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none"
|
|
@@ -454,132 +530,99 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
|
|
|
454
530
|
{searchQuery && (
|
|
455
531
|
<button
|
|
456
532
|
type="button"
|
|
533
|
+
aria-label="Clear search"
|
|
457
534
|
onClick={() => setSearchQuery('')}
|
|
458
|
-
className="shrink-0
|
|
535
|
+
className="-mr-2 hidden h-full max-w-full shrink-0 cursor-pointer items-center rounded-r-md border-0 bg-transparent px-2.5 font-inherit text-base text-gray-900 no-underline transition-colors duration-150 ease-in hover:text-gray-1000 focus-visible:-outline-offset-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--ds-focus-color)] min-[961px]:flex"
|
|
459
536
|
>
|
|
460
|
-
<
|
|
537
|
+
<Kbd variant="outline" size="search">
|
|
538
|
+
Esc
|
|
539
|
+
</Kbd>
|
|
461
540
|
</button>
|
|
462
541
|
)}
|
|
463
542
|
</div>
|
|
464
543
|
}
|
|
465
544
|
endHeader={
|
|
466
|
-
<TimelineHeader
|
|
467
|
-
viewStart={viewport.start}
|
|
468
|
-
viewDuration={viewDuration}
|
|
469
|
-
rootStart={root.startTime}
|
|
470
|
-
compression={compression}
|
|
471
|
-
isZoomed={isZoomed}
|
|
472
|
-
onResetZoom={resetZoom}
|
|
473
|
-
hoverInfo={hoverInfo}
|
|
474
|
-
/>
|
|
545
|
+
<TimelineHeader markers={timeMarkers} hoverInfo={hoverInfo} />
|
|
475
546
|
}
|
|
476
547
|
>
|
|
477
548
|
<div className="block overflow-visible">
|
|
478
549
|
<EventList
|
|
479
|
-
spans={
|
|
550
|
+
spans={trace.spans}
|
|
480
551
|
activeSpanId={activeSpanId}
|
|
552
|
+
searchResult={searchResult}
|
|
481
553
|
onSelectSpan={handleSelectSpan}
|
|
482
554
|
/>
|
|
555
|
+
<div ref={loadMoreSentinelRef} className="flex justify-center">
|
|
556
|
+
{isLoadingMore ? (
|
|
557
|
+
<div className="flex items-center justify-center gap-2 py-3 text-sm text-gray-800">
|
|
558
|
+
<Spinner size={14} />
|
|
559
|
+
<span>Loading spans…</span>
|
|
560
|
+
</div>
|
|
561
|
+
) : null}
|
|
562
|
+
</div>
|
|
483
563
|
</div>
|
|
564
|
+
{/* biome-ignore lint/a11y/noStaticElementInteractions: timeline hover and wheel gestures are pointer-only annotations */}
|
|
484
565
|
<div
|
|
485
566
|
ref={timelineRef}
|
|
486
|
-
|
|
567
|
+
id="trace-timeline"
|
|
568
|
+
className="@container block min-h-0 overflow-visible relative"
|
|
487
569
|
onDoubleClick={resetZoom}
|
|
488
570
|
onMouseMove={handleTimelineMouseMove}
|
|
489
571
|
onMouseLeave={handleTimelineMouseLeave}
|
|
490
572
|
>
|
|
491
573
|
<Timeline
|
|
492
|
-
spans={
|
|
493
|
-
|
|
574
|
+
spans={trace.spans}
|
|
575
|
+
viewStart={viewport.start}
|
|
576
|
+
viewEnd={viewport.end}
|
|
577
|
+
markers={timeMarkers}
|
|
494
578
|
selectedId={activeSpanId}
|
|
579
|
+
searchResult={searchResult}
|
|
495
580
|
onSelect={handleSelectSpan}
|
|
581
|
+
onRevealTime={handleRevealTime}
|
|
496
582
|
hoverFraction={hoverFraction}
|
|
497
583
|
altHeld={altHeld}
|
|
498
584
|
/>
|
|
585
|
+
<TraceShortcutHelper
|
|
586
|
+
hasMultipleSpans={trace.spans.length > 1}
|
|
587
|
+
reducedMotion={reducedMotion}
|
|
588
|
+
/>
|
|
499
589
|
</div>
|
|
500
590
|
</SplitPane>
|
|
591
|
+
<div className="absolute right-3 bottom-3 z-[5] flex items-center border border-gray-alpha-400 rounded-md bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400">
|
|
592
|
+
<IconButton
|
|
593
|
+
variant="muted"
|
|
594
|
+
size="small"
|
|
595
|
+
onClick={zoomOut}
|
|
596
|
+
disabled={isAtMinZoom}
|
|
597
|
+
aria-label="Zoom out"
|
|
598
|
+
>
|
|
599
|
+
<ZoomOut className="w-4 h-4" />
|
|
600
|
+
</IconButton>
|
|
601
|
+
<IconButton
|
|
602
|
+
variant="muted"
|
|
603
|
+
size="small"
|
|
604
|
+
onClick={resetZoom}
|
|
605
|
+
aria-label="Reset zoom"
|
|
606
|
+
>
|
|
607
|
+
<RotateCcw className="w-3.5 h-3.5" />
|
|
608
|
+
</IconButton>
|
|
609
|
+
<IconButton
|
|
610
|
+
variant="muted"
|
|
611
|
+
size="small"
|
|
612
|
+
onClick={zoomIn}
|
|
613
|
+
disabled={isAtMaxZoom}
|
|
614
|
+
aria-label="Zoom in"
|
|
615
|
+
>
|
|
616
|
+
<ZoomIn className="w-4 h-4" />
|
|
617
|
+
</IconButton>
|
|
618
|
+
</div>
|
|
501
619
|
</div>
|
|
502
620
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
<div className="flex items-start justify-between gap-2">
|
|
509
|
-
<div className="min-w-0 flex-1">
|
|
510
|
-
<span className="text-[15px] font-semibold text-gray-1000 truncate block">
|
|
511
|
-
{selectedSpanName}
|
|
512
|
-
</span>
|
|
513
|
-
{selectedResourceId && (
|
|
514
|
-
<div className="mt-1 flex items-center gap-2">
|
|
515
|
-
{selectedResource && (
|
|
516
|
-
<span
|
|
517
|
-
className={`inline-flex items-center rounded-md px-1.5 py-0.5 text-[11px] font-medium leading-none shrink-0 ${
|
|
518
|
-
selectedResource === 'step'
|
|
519
|
-
? 'bg-green-200 text-green-900'
|
|
520
|
-
: selectedResource === 'run'
|
|
521
|
-
? 'bg-blue-200 text-blue-900'
|
|
522
|
-
: selectedResource === 'hook'
|
|
523
|
-
? 'bg-yellow-200 text-yellow-900'
|
|
524
|
-
: 'bg-gray-200 text-gray-900'
|
|
525
|
-
}`}
|
|
526
|
-
>
|
|
527
|
-
{selectedResource.charAt(0).toUpperCase() +
|
|
528
|
-
selectedResource.slice(1)}
|
|
529
|
-
</span>
|
|
530
|
-
)}
|
|
531
|
-
<div
|
|
532
|
-
className="flex items-center gap-1 text-[13px] font-mono text-gray-700 min-w-0"
|
|
533
|
-
title={selectedResourceId}
|
|
534
|
-
>
|
|
535
|
-
<span className="truncate">{selectedResourceId}</span>
|
|
536
|
-
<CopyButton
|
|
537
|
-
copyText={selectedResourceId}
|
|
538
|
-
ariaLabel="Copy ID"
|
|
539
|
-
className="shrink-0"
|
|
540
|
-
/>
|
|
541
|
-
</div>
|
|
542
|
-
</div>
|
|
543
|
-
)}
|
|
544
|
-
</div>
|
|
545
|
-
<button
|
|
546
|
-
type="button"
|
|
547
|
-
className="p-1 rounded-md text-gray-900 hover:text-gray-1000 hover:bg-gray-alpha-200 transition-colors shrink-0"
|
|
548
|
-
onClick={clearActiveSpan}
|
|
549
|
-
>
|
|
550
|
-
<X className="w-4 h-4" />
|
|
551
|
-
</button>
|
|
552
|
-
</div>
|
|
553
|
-
</div>
|
|
554
|
-
{/* Panel body */}
|
|
555
|
-
<div className="flex-1 overflow-y-auto">
|
|
556
|
-
<ErrorBoundary>
|
|
557
|
-
<EntityDetailPanel
|
|
558
|
-
run={sidebar.run}
|
|
559
|
-
onStreamClick={sidebar.onStreamClick}
|
|
560
|
-
onRunClick={sidebar.onRunClick}
|
|
561
|
-
spanDetailData={sidebar.spanDetailData}
|
|
562
|
-
spanDetailError={sidebar.spanDetailError}
|
|
563
|
-
spanDetailLoading={sidebar.spanDetailLoading}
|
|
564
|
-
onSpanSelect={sidebar.onSpanSelect}
|
|
565
|
-
onWakeUpSleep={sidebar.onWakeUpSleep}
|
|
566
|
-
onLoadEventData={sidebar.onLoadEventData}
|
|
567
|
-
onResolveHook={sidebar.onResolveHook}
|
|
568
|
-
encryptionKey={sidebar.encryptionKey}
|
|
569
|
-
onDecrypt={sidebar.onDecrypt}
|
|
570
|
-
isDecrypting={sidebar.isDecrypting}
|
|
571
|
-
selectedSpan={selectedSpan}
|
|
572
|
-
/>
|
|
573
|
-
</ErrorBoundary>
|
|
574
|
-
</div>
|
|
575
|
-
</aside>
|
|
576
|
-
) : activeSpan ? (
|
|
577
|
-
<DetailPanel
|
|
578
|
-
span={activeSpan}
|
|
579
|
-
rootStart={root.startTime}
|
|
580
|
-
onClose={clearActiveSpan}
|
|
581
|
-
/>
|
|
582
|
-
) : null}
|
|
621
|
+
<TraceDetailPanel
|
|
622
|
+
containerRef={paneRootRef}
|
|
623
|
+
onNavigateToSpan={navigateToSpan}
|
|
624
|
+
onClose={handleClearActiveSpan}
|
|
625
|
+
/>
|
|
583
626
|
</div>
|
|
584
627
|
);
|
|
585
628
|
}
|