@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,43 +1,38 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Reusable data inspector
|
|
4
|
+
* Reusable data inspector for the o11y UI.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Renders JSON as a collapsible tree: bracket notation (`{ … }` / `[ … ]`),
|
|
7
|
+
* colored keys, typed value colors, `▸`/`▾` disclosure icons, and a `...`
|
|
8
|
+
* collapsed indicator.
|
|
9
|
+
*
|
|
10
|
+
* On top of plain JSON it handles the workflow-specific value types: StreamRef /
|
|
11
|
+
* RunRef badges, encrypted markers, decoded byte streams, Dates, and named
|
|
12
|
+
* class instances.
|
|
9
13
|
*/
|
|
10
14
|
|
|
11
15
|
import { Lock } from 'lucide-react';
|
|
12
16
|
import {
|
|
13
17
|
createContext,
|
|
18
|
+
type KeyboardEvent as ReactKeyboardEvent,
|
|
19
|
+
type MouseEvent as ReactMouseEvent,
|
|
20
|
+
type ReactNode,
|
|
21
|
+
type RefObject,
|
|
14
22
|
useContext,
|
|
15
|
-
|
|
23
|
+
useId,
|
|
16
24
|
useMemo,
|
|
17
25
|
useRef,
|
|
18
26
|
useState,
|
|
19
27
|
} from 'react';
|
|
20
|
-
import {
|
|
21
|
-
ObjectInspector,
|
|
22
|
-
ObjectLabel,
|
|
23
|
-
ObjectName,
|
|
24
|
-
ObjectRootLabel,
|
|
25
|
-
ObjectValue,
|
|
26
|
-
} from 'react-inspector';
|
|
27
|
-
import { useDarkMode } from '../../hooks/use-dark-mode';
|
|
28
28
|
import { ENCRYPTED_DISPLAY_NAME } from '../../lib/hydration';
|
|
29
29
|
import {
|
|
30
30
|
type DecodedStreamChunkSource,
|
|
31
31
|
type FormattedStreamChunkDisplay,
|
|
32
32
|
formatArrayBufferViewForDisplay,
|
|
33
33
|
} from '../../lib/stream-display';
|
|
34
|
-
import {
|
|
35
|
-
|
|
36
|
-
inspectorThemeDark,
|
|
37
|
-
inspectorThemeExtendedDark,
|
|
38
|
-
inspectorThemeExtendedLight,
|
|
39
|
-
inspectorThemeLight,
|
|
40
|
-
} from './inspector-theme';
|
|
34
|
+
import { Button } from './button';
|
|
35
|
+
import { CLS, JSON_VIEW_STYLES } from './data-inspector.styles';
|
|
41
36
|
import { Spinner } from './spinner';
|
|
42
37
|
|
|
43
38
|
// ---------------------------------------------------------------------------
|
|
@@ -66,6 +61,13 @@ interface BytesDisplay {
|
|
|
66
61
|
decodedFrom?: DecodedStreamChunkSource;
|
|
67
62
|
}
|
|
68
63
|
|
|
64
|
+
interface ClassInstanceRef {
|
|
65
|
+
__type: typeof CLASS_INSTANCE_REF_TYPE;
|
|
66
|
+
className: string;
|
|
67
|
+
classId: string;
|
|
68
|
+
data: unknown;
|
|
69
|
+
}
|
|
70
|
+
|
|
69
71
|
function deserializeChunkText(text: string): string {
|
|
70
72
|
try {
|
|
71
73
|
const parsed = JSON.parse(text);
|
|
@@ -105,12 +107,7 @@ export function isBytesDisplay(value: unknown): value is BytesDisplay {
|
|
|
105
107
|
return desc?.value === BYTES_DISPLAY_TYPE;
|
|
106
108
|
}
|
|
107
109
|
|
|
108
|
-
function isClassInstanceRef(value: unknown): value is {
|
|
109
|
-
__type: string;
|
|
110
|
-
className: string;
|
|
111
|
-
classId: string;
|
|
112
|
-
data: unknown;
|
|
113
|
-
} {
|
|
110
|
+
function isClassInstanceRef(value: unknown): value is ClassInstanceRef {
|
|
114
111
|
return (
|
|
115
112
|
value !== null &&
|
|
116
113
|
typeof value === 'object' &&
|
|
@@ -119,6 +116,15 @@ function isClassInstanceRef(value: unknown): value is {
|
|
|
119
116
|
);
|
|
120
117
|
}
|
|
121
118
|
|
|
119
|
+
function isEncryptedMarker(value: unknown): boolean {
|
|
120
|
+
return (
|
|
121
|
+
value !== null &&
|
|
122
|
+
typeof value === 'object' &&
|
|
123
|
+
(value as { constructor?: { name?: string } }).constructor?.name ===
|
|
124
|
+
ENCRYPTED_DISPLAY_NAME
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
122
128
|
// ---------------------------------------------------------------------------
|
|
123
129
|
// Stream click context (passed through from the panel)
|
|
124
130
|
// ---------------------------------------------------------------------------
|
|
@@ -138,6 +144,7 @@ export const StreamClickContext = createContext<
|
|
|
138
144
|
export type DecryptClickContextValue = {
|
|
139
145
|
onDecrypt: () => void;
|
|
140
146
|
isDecrypting: boolean;
|
|
147
|
+
hasEncryptedData?: boolean;
|
|
141
148
|
};
|
|
142
149
|
|
|
143
150
|
export const DecryptClickContext = createContext<
|
|
@@ -148,37 +155,30 @@ export const RunClickContext = createContext<
|
|
|
148
155
|
((runId: string) => void) | undefined
|
|
149
156
|
>(undefined);
|
|
150
157
|
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// Workflow-specific value renderers (badges, encrypted markers, byte streams)
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
|
|
151
162
|
function EncryptedInlineLabel() {
|
|
152
163
|
const ctx = useContext(DecryptClickContext);
|
|
153
164
|
if (ctx) {
|
|
154
165
|
return (
|
|
155
|
-
<
|
|
156
|
-
|
|
157
|
-
className="
|
|
158
|
-
style={{
|
|
159
|
-
backgroundColor: 'var(--ds-gray-100)',
|
|
160
|
-
color: 'var(--ds-gray-700)',
|
|
161
|
-
border: '1px solid var(--ds-gray-400)',
|
|
162
|
-
fontStyle: 'italic',
|
|
163
|
-
opacity: ctx.isDecrypting ? 0.6 : 1,
|
|
164
|
-
}}
|
|
166
|
+
<Button
|
|
167
|
+
size="xs"
|
|
168
|
+
className="align-baseline gap-x-1"
|
|
165
169
|
disabled={ctx.isDecrypting}
|
|
166
170
|
onClick={(e) => {
|
|
167
171
|
e.stopPropagation();
|
|
168
172
|
ctx.onDecrypt();
|
|
169
173
|
}}
|
|
170
|
-
title="Click to decrypt"
|
|
171
174
|
>
|
|
172
175
|
{ctx.isDecrypting ? (
|
|
173
|
-
<Spinner size={
|
|
176
|
+
<Spinner size={10} />
|
|
174
177
|
) : (
|
|
175
|
-
<Lock
|
|
176
|
-
className="h-3 w-3"
|
|
177
|
-
style={{ display: 'inline', flexShrink: 0 }}
|
|
178
|
-
/>
|
|
178
|
+
<Lock className="h-3 w-3" />
|
|
179
179
|
)}
|
|
180
|
-
<span>
|
|
181
|
-
</
|
|
180
|
+
<span>Decrypt</span>
|
|
181
|
+
</Button>
|
|
182
182
|
);
|
|
183
183
|
}
|
|
184
184
|
return (
|
|
@@ -196,6 +196,7 @@ function EncryptedInlineLabel() {
|
|
|
196
196
|
</span>
|
|
197
197
|
);
|
|
198
198
|
}
|
|
199
|
+
|
|
199
200
|
function StreamRefInline({ streamRef }: { streamRef: StreamRef }) {
|
|
200
201
|
const onStreamClick = useContext(StreamClickContext);
|
|
201
202
|
const [hovered, setHovered] = useState(false);
|
|
@@ -249,14 +250,6 @@ function RunRefInline({ runRef }: { runRef: RunRef }) {
|
|
|
249
250
|
);
|
|
250
251
|
}
|
|
251
252
|
|
|
252
|
-
// ---------------------------------------------------------------------------
|
|
253
|
-
// Extended theme context (for colors react-inspector doesn't support natively)
|
|
254
|
-
// ---------------------------------------------------------------------------
|
|
255
|
-
|
|
256
|
-
const ExtendedThemeContext = createContext<InspectorThemeExtended>(
|
|
257
|
-
inspectorThemeExtendedLight
|
|
258
|
-
);
|
|
259
|
-
|
|
260
253
|
function DecodedBytesChunk({
|
|
261
254
|
decodedText,
|
|
262
255
|
source,
|
|
@@ -370,162 +363,474 @@ function DecodedBytesInspector({
|
|
|
370
363
|
);
|
|
371
364
|
}
|
|
372
365
|
|
|
373
|
-
function
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
366
|
+
function BytesDisplayValue({ display }: { display: BytesDisplay }) {
|
|
367
|
+
if (display.decodedFrom) {
|
|
368
|
+
return (
|
|
369
|
+
<DecodedBytesChunk
|
|
370
|
+
decodedText={display.text}
|
|
371
|
+
source={display.decodedFrom}
|
|
372
|
+
/>
|
|
373
|
+
);
|
|
374
|
+
}
|
|
380
375
|
return (
|
|
381
|
-
<
|
|
382
|
-
|
|
383
|
-
{
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
source={display.decodedFrom}
|
|
388
|
-
/>
|
|
389
|
-
) : (
|
|
390
|
-
<span
|
|
391
|
-
className="whitespace-pre-wrap break-words"
|
|
392
|
-
style={{ color: 'var(--ds-gray-1000)' }}
|
|
393
|
-
>
|
|
394
|
-
{display.text}
|
|
395
|
-
</span>
|
|
396
|
-
)}
|
|
397
|
-
</div>
|
|
376
|
+
<span
|
|
377
|
+
className="whitespace-pre-wrap break-words"
|
|
378
|
+
style={{ color: 'var(--ds-gray-1000)' }}
|
|
379
|
+
>
|
|
380
|
+
{display.text}
|
|
381
|
+
</span>
|
|
398
382
|
);
|
|
399
383
|
}
|
|
400
384
|
|
|
401
385
|
// ---------------------------------------------------------------------------
|
|
402
|
-
//
|
|
386
|
+
// Tree renderer
|
|
403
387
|
// ---------------------------------------------------------------------------
|
|
404
388
|
|
|
389
|
+
type Entry = [field: string | undefined, value: unknown];
|
|
390
|
+
|
|
391
|
+
interface NodeContext {
|
|
392
|
+
level: number;
|
|
393
|
+
shouldExpand: (level: number) => boolean;
|
|
394
|
+
outerRef: RefObject<HTMLDivElement | null>;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** Field names are rendered unquoted (empty string shows as `""`). */
|
|
398
|
+
function formatField(field: string): string {
|
|
399
|
+
return field === '' ? '""' : field;
|
|
400
|
+
}
|
|
401
|
+
|
|
405
402
|
/**
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
* react-inspector renders Date instances as unstyled plain text (no theme
|
|
410
|
-
* key exists for them), so we intercept here and apply the magenta color
|
|
411
|
-
* from our extended theme — matching Node.js util.inspect()'s date style.
|
|
412
|
-
*
|
|
413
|
-
* Default nodeRenderer reference:
|
|
414
|
-
* https://github.com/storybookjs/react-inspector/blob/main/README.md#noderenderer
|
|
403
|
+
* Describe an object/array/map/set as an expandable container. Returns null for
|
|
404
|
+
* values that should render as a primitive. `prefix` carries a class name shown
|
|
405
|
+
* before the opening bracket (Map/Set and named class instances).
|
|
415
406
|
*/
|
|
416
|
-
function
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
407
|
+
function describeContainer(
|
|
408
|
+
value: unknown
|
|
409
|
+
): { entries: Entry[]; open: string; close: string; prefix?: string } | null {
|
|
410
|
+
if (Array.isArray(value)) {
|
|
411
|
+
return {
|
|
412
|
+
entries: value.map((item) => [undefined, item] as Entry),
|
|
413
|
+
open: '[',
|
|
414
|
+
close: ']',
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
if (value instanceof Map) {
|
|
418
|
+
return {
|
|
419
|
+
entries: Array.from(value.entries(), ([key, val]) => [
|
|
420
|
+
String(key),
|
|
421
|
+
val,
|
|
422
|
+
]) as Entry[],
|
|
423
|
+
open: '{',
|
|
424
|
+
close: '}',
|
|
425
|
+
prefix: 'Map',
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
if (value instanceof Set) {
|
|
429
|
+
return {
|
|
430
|
+
entries: Array.from(value.values(), (item) => [undefined, item] as Entry),
|
|
431
|
+
open: '[',
|
|
432
|
+
close: ']',
|
|
433
|
+
prefix: 'Set',
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
if (value !== null && typeof value === 'object') {
|
|
437
|
+
const name = (value as { constructor?: { name?: string } }).constructor
|
|
438
|
+
?.name;
|
|
439
|
+
return {
|
|
440
|
+
entries: Object.entries(value) as Entry[],
|
|
441
|
+
open: '{',
|
|
442
|
+
close: '}',
|
|
443
|
+
prefix: name && name !== 'Object' ? name : undefined,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function describePrimitive(value: unknown): { text: string; cls: string } {
|
|
450
|
+
if (value === null) return { text: 'null', cls: CLS.null };
|
|
451
|
+
if (value === undefined) return { text: 'undefined', cls: CLS.undefined };
|
|
452
|
+
if (typeof value === 'string' || value instanceof String) {
|
|
453
|
+
return { text: `"${String(value)}"`, cls: CLS.string };
|
|
454
|
+
}
|
|
455
|
+
if (typeof value === 'boolean' || value instanceof Boolean) {
|
|
456
|
+
return { text: String(value), cls: CLS.boolean };
|
|
457
|
+
}
|
|
458
|
+
if (typeof value === 'number' || value instanceof Number) {
|
|
459
|
+
return { text: String(value), cls: CLS.number };
|
|
460
|
+
}
|
|
461
|
+
if (typeof value === 'bigint') {
|
|
462
|
+
return { text: `${value.toString()}n`, cls: CLS.number };
|
|
463
|
+
}
|
|
464
|
+
return { text: String(value), cls: CLS.punctuation };
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function Label({ field, clickable }: { field?: string; clickable?: boolean }) {
|
|
468
|
+
if (field === undefined) return null;
|
|
469
|
+
return (
|
|
470
|
+
<span className={clickable ? CLS.clickableLabel : CLS.label}>
|
|
471
|
+
{`${formatField(field)}:`}
|
|
472
|
+
</span>
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function Comma({ isLast }: { isLast: boolean }) {
|
|
477
|
+
if (isLast) return null;
|
|
478
|
+
return <span className={CLS.punctuation}>,</span>;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/** A non-expandable row: `field: <value>`. */
|
|
482
|
+
function LeafRow({
|
|
483
|
+
field,
|
|
484
|
+
isLast,
|
|
485
|
+
children,
|
|
421
486
|
}: {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
isNonenumerable?: boolean;
|
|
426
|
-
expanded?: boolean;
|
|
487
|
+
field?: string;
|
|
488
|
+
isLast: boolean;
|
|
489
|
+
children: ReactNode;
|
|
427
490
|
}) {
|
|
428
|
-
|
|
491
|
+
return (
|
|
492
|
+
<div className={CLS.child} role="treeitem" tabIndex={-1}>
|
|
493
|
+
<Label field={field} />
|
|
494
|
+
{children}
|
|
495
|
+
<Comma isLast={isLast} />
|
|
496
|
+
</div>
|
|
497
|
+
);
|
|
498
|
+
}
|
|
429
499
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
500
|
+
function PrimitiveValue({ field, value, isLast }: NodeProps) {
|
|
501
|
+
const { text, cls } = describePrimitive(value);
|
|
502
|
+
return (
|
|
503
|
+
<LeafRow field={field} isLast={isLast}>
|
|
504
|
+
<span className={cls}>{text}</span>
|
|
505
|
+
</LeafRow>
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function EmptyContainer({
|
|
510
|
+
field,
|
|
511
|
+
prefix,
|
|
512
|
+
open,
|
|
513
|
+
close,
|
|
514
|
+
isLast,
|
|
515
|
+
}: {
|
|
516
|
+
field?: string;
|
|
517
|
+
prefix?: string;
|
|
518
|
+
open: string;
|
|
519
|
+
close: string;
|
|
520
|
+
isLast: boolean;
|
|
521
|
+
}) {
|
|
522
|
+
return (
|
|
523
|
+
<div className={CLS.child} role="treeitem" tabIndex={-1}>
|
|
524
|
+
<Label field={field} />
|
|
525
|
+
{prefix ? <span className={CLS.className}>{prefix}</span> : null}
|
|
526
|
+
<span className={CLS.punctuation}>{open}</span>
|
|
527
|
+
<span className={CLS.punctuation}>{close}</span>
|
|
528
|
+
<Comma isLast={isLast} />
|
|
529
|
+
</div>
|
|
530
|
+
);
|
|
531
|
+
}
|
|
433
532
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
533
|
+
function focusExpander(
|
|
534
|
+
button: HTMLElement,
|
|
535
|
+
outerRef: RefObject<HTMLDivElement | null>
|
|
536
|
+
) {
|
|
537
|
+
const previous = outerRef.current?.querySelector<HTMLElement>(
|
|
538
|
+
'[data-json-expander][tabindex="0"]'
|
|
539
|
+
);
|
|
540
|
+
if (previous) previous.tabIndex = -1;
|
|
541
|
+
button.tabIndex = 0;
|
|
542
|
+
button.focus();
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function moveExpanderFocus(
|
|
546
|
+
outerRef: RefObject<HTMLDivElement | null>,
|
|
547
|
+
direction: 1 | -1
|
|
548
|
+
) {
|
|
549
|
+
const root = outerRef.current;
|
|
550
|
+
if (!root) return;
|
|
551
|
+
const buttons = root.querySelectorAll<HTMLElement>('[data-json-expander]');
|
|
552
|
+
let current = -1;
|
|
553
|
+
for (let i = 0; i < buttons.length; i += 1) {
|
|
554
|
+
if (buttons[i].tabIndex === 0) {
|
|
555
|
+
current = i;
|
|
556
|
+
break;
|
|
443
557
|
}
|
|
558
|
+
}
|
|
559
|
+
if (current < 0) return;
|
|
560
|
+
const next = (current + direction + buttons.length) % buttons.length;
|
|
561
|
+
buttons[current].tabIndex = -1;
|
|
562
|
+
buttons[next].tabIndex = 0;
|
|
563
|
+
buttons[next].focus();
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function ExpandableContainer({
|
|
567
|
+
field,
|
|
568
|
+
entries,
|
|
569
|
+
open,
|
|
570
|
+
close,
|
|
571
|
+
prefix,
|
|
572
|
+
ctx,
|
|
573
|
+
isLast,
|
|
574
|
+
}: {
|
|
575
|
+
field?: string;
|
|
576
|
+
entries: Entry[];
|
|
577
|
+
open: string;
|
|
578
|
+
close: string;
|
|
579
|
+
prefix?: string;
|
|
580
|
+
ctx: NodeContext;
|
|
581
|
+
isLast: boolean;
|
|
582
|
+
}) {
|
|
583
|
+
const { level, shouldExpand, outerRef } = ctx;
|
|
584
|
+
const [expanded, setExpanded] = useState(() => shouldExpand(level));
|
|
585
|
+
const rowRef = useRef<HTMLDivElement>(null);
|
|
586
|
+
const contentsId = useId();
|
|
587
|
+
|
|
588
|
+
if (entries.length === 0) {
|
|
444
589
|
return (
|
|
445
|
-
<
|
|
446
|
-
|
|
447
|
-
{
|
|
448
|
-
{
|
|
449
|
-
|
|
590
|
+
<EmptyContainer
|
|
591
|
+
field={field}
|
|
592
|
+
prefix={prefix}
|
|
593
|
+
open={open}
|
|
594
|
+
close={close}
|
|
595
|
+
isLast={isLast}
|
|
596
|
+
/>
|
|
450
597
|
);
|
|
451
598
|
}
|
|
452
599
|
|
|
453
|
-
|
|
454
|
-
|
|
600
|
+
const toggle = () => {
|
|
601
|
+
setExpanded((value) => !value);
|
|
602
|
+
if (rowRef.current) focusExpander(rowRef.current, outerRef);
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
// Toggle only for clicks that land on this row itself; clicks bubbling up out
|
|
606
|
+
// of a nested treeitem are handled by that descendant's own row.
|
|
607
|
+
const onClick = (event: ReactMouseEvent) => {
|
|
608
|
+
if (
|
|
609
|
+
(event.target as HTMLElement).closest('[role="treeitem"]') !==
|
|
610
|
+
event.currentTarget
|
|
611
|
+
) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
toggle();
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
const onKeyDown = (event: ReactKeyboardEvent) => {
|
|
618
|
+
if (event.key === 'ArrowRight') {
|
|
619
|
+
event.preventDefault();
|
|
620
|
+
setExpanded(true);
|
|
621
|
+
} else if (event.key === 'ArrowLeft') {
|
|
622
|
+
event.preventDefault();
|
|
623
|
+
setExpanded(false);
|
|
624
|
+
} else if (event.key === 'ArrowUp') {
|
|
625
|
+
event.preventDefault();
|
|
626
|
+
moveExpanderFocus(outerRef, -1);
|
|
627
|
+
} else if (event.key === 'ArrowDown') {
|
|
628
|
+
event.preventDefault();
|
|
629
|
+
moveExpanderFocus(outerRef, 1);
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
const lastIndex = entries.length - 1;
|
|
634
|
+
|
|
635
|
+
return (
|
|
636
|
+
// The treeitem row is the focusable, keyboard-operable control (roving
|
|
637
|
+
// tabindex + arrow keys); the disclosure marker below is purely decorative.
|
|
638
|
+
<div
|
|
639
|
+
className={CLS.child}
|
|
640
|
+
role="treeitem"
|
|
641
|
+
aria-expanded={expanded}
|
|
642
|
+
aria-controls={expanded ? contentsId : undefined}
|
|
643
|
+
data-json-expander
|
|
644
|
+
ref={rowRef}
|
|
645
|
+
tabIndex={level === 0 ? 0 : -1}
|
|
646
|
+
onClick={onClick}
|
|
647
|
+
onKeyDown={onKeyDown}
|
|
648
|
+
>
|
|
649
|
+
<span
|
|
650
|
+
className={expanded ? CLS.collapseIcon : CLS.expandIcon}
|
|
651
|
+
aria-hidden="true"
|
|
652
|
+
/>
|
|
653
|
+
{field !== undefined && (
|
|
654
|
+
<span className={CLS.clickableLabel}>{`${formatField(field)}:`}</span>
|
|
655
|
+
)}
|
|
656
|
+
{prefix ? <span className={CLS.className}>{prefix}</span> : null}
|
|
657
|
+
<span className={CLS.punctuation}>{open}</span>
|
|
658
|
+
{expanded ? (
|
|
659
|
+
// biome-ignore lint/a11y/useSemanticElements: ARIA tree group is the correct role here
|
|
660
|
+
<ul id={contentsId} className={CLS.childFields} role="group">
|
|
661
|
+
{entries.map(([childField, childValue], index) => (
|
|
662
|
+
<DataRender
|
|
663
|
+
key={childField ?? index}
|
|
664
|
+
field={childField}
|
|
665
|
+
value={childValue}
|
|
666
|
+
isLast={index === lastIndex}
|
|
667
|
+
ctx={{ ...ctx, level: level + 1 }}
|
|
668
|
+
/>
|
|
669
|
+
))}
|
|
670
|
+
</ul>
|
|
671
|
+
) : (
|
|
672
|
+
<span className={CLS.collapsedContent} aria-hidden="true" />
|
|
673
|
+
)}
|
|
674
|
+
<span className={CLS.punctuation}>{close}</span>
|
|
675
|
+
<Comma isLast={isLast} />
|
|
676
|
+
</div>
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
interface NodeProps {
|
|
681
|
+
field?: string;
|
|
682
|
+
value: unknown;
|
|
683
|
+
isLast: boolean;
|
|
684
|
+
ctx: NodeContext;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
function DataRender({ field, value, isLast, ctx }: NodeProps) {
|
|
688
|
+
if (isBytesDisplay(value)) {
|
|
455
689
|
return (
|
|
456
|
-
<
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
<StreamRefInline streamRef={data} />
|
|
460
|
-
</span>
|
|
690
|
+
<LeafRow field={field} isLast={isLast}>
|
|
691
|
+
<BytesDisplayValue display={value} />
|
|
692
|
+
</LeafRow>
|
|
461
693
|
);
|
|
462
694
|
}
|
|
463
|
-
|
|
464
|
-
// RunRef → inline clickable badge linking to the target run
|
|
465
|
-
if (isRunRef(data)) {
|
|
695
|
+
if (isEncryptedMarker(value)) {
|
|
466
696
|
return (
|
|
467
|
-
<
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
<RunRefInline runRef={data} />
|
|
471
|
-
</span>
|
|
697
|
+
<LeafRow field={field} isLast={isLast}>
|
|
698
|
+
<EncryptedInlineLabel />
|
|
699
|
+
</LeafRow>
|
|
472
700
|
);
|
|
473
701
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
702
|
+
if (isStreamRef(value)) {
|
|
703
|
+
return (
|
|
704
|
+
<LeafRow field={field} isLast={isLast}>
|
|
705
|
+
<StreamRefInline streamRef={value} />
|
|
706
|
+
</LeafRow>
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
if (isRunRef(value)) {
|
|
710
|
+
return (
|
|
711
|
+
<LeafRow field={field} isLast={isLast}>
|
|
712
|
+
<RunRefInline runRef={value} />
|
|
713
|
+
</LeafRow>
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
if (value instanceof Date) {
|
|
717
|
+
return (
|
|
718
|
+
<LeafRow field={field} isLast={isLast}>
|
|
719
|
+
<span className={CLS.date}>{value.toISOString()}</span>
|
|
720
|
+
</LeafRow>
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
if (value instanceof RegExp) {
|
|
724
|
+
return (
|
|
725
|
+
<LeafRow field={field} isLast={isLast}>
|
|
726
|
+
<span className={CLS.regexp}>{value.toString()}</span>
|
|
727
|
+
</LeafRow>
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
if (isClassInstanceRef(value)) {
|
|
480
731
|
return (
|
|
481
|
-
<
|
|
482
|
-
|
|
483
|
-
{
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
732
|
+
<ClassInstanceNode
|
|
733
|
+
field={field}
|
|
734
|
+
instance={value}
|
|
735
|
+
isLast={isLast}
|
|
736
|
+
ctx={ctx}
|
|
737
|
+
/>
|
|
487
738
|
);
|
|
488
739
|
}
|
|
489
740
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
if (data instanceof Date) {
|
|
493
|
-
const dateStr = data.toISOString();
|
|
494
|
-
if (depth === 0) {
|
|
495
|
-
return (
|
|
496
|
-
<span style={{ color: extendedTheme.OBJECT_VALUE_DATE_COLOR }}>
|
|
497
|
-
{dateStr}
|
|
498
|
-
</span>
|
|
499
|
-
);
|
|
500
|
-
}
|
|
741
|
+
const container = describeContainer(value);
|
|
742
|
+
if (container) {
|
|
501
743
|
return (
|
|
502
|
-
<
|
|
503
|
-
|
|
504
|
-
{
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
744
|
+
<ExpandableContainer
|
|
745
|
+
field={field}
|
|
746
|
+
entries={container.entries}
|
|
747
|
+
open={container.open}
|
|
748
|
+
close={container.close}
|
|
749
|
+
prefix={container.prefix}
|
|
750
|
+
ctx={ctx}
|
|
751
|
+
isLast={isLast}
|
|
752
|
+
/>
|
|
509
753
|
);
|
|
510
754
|
}
|
|
511
755
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
756
|
+
return (
|
|
757
|
+
<PrimitiveValue field={field} value={value} isLast={isLast} ctx={ctx} />
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function ClassInstanceNode({
|
|
762
|
+
field,
|
|
763
|
+
instance,
|
|
764
|
+
isLast,
|
|
765
|
+
ctx,
|
|
766
|
+
}: {
|
|
767
|
+
field?: string;
|
|
768
|
+
instance: ClassInstanceRef;
|
|
769
|
+
isLast: boolean;
|
|
770
|
+
ctx: NodeContext;
|
|
771
|
+
}) {
|
|
772
|
+
const container = describeContainer(instance.data);
|
|
773
|
+
if (container) {
|
|
774
|
+
return (
|
|
775
|
+
<ExpandableContainer
|
|
776
|
+
field={field}
|
|
777
|
+
entries={container.entries}
|
|
778
|
+
open={container.open}
|
|
779
|
+
close={container.close}
|
|
780
|
+
prefix={instance.className}
|
|
781
|
+
ctx={ctx}
|
|
782
|
+
isLast={isLast}
|
|
783
|
+
/>
|
|
784
|
+
);
|
|
515
785
|
}
|
|
786
|
+
const { text, cls } = describePrimitive(instance.data);
|
|
516
787
|
return (
|
|
517
|
-
<
|
|
788
|
+
<LeafRow field={field} isLast={isLast}>
|
|
789
|
+
<span className={CLS.className}>{instance.className}</span>
|
|
790
|
+
<span className={cls}>{text}</span>
|
|
791
|
+
</LeafRow>
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
function JsonTree({
|
|
796
|
+
data,
|
|
797
|
+
name,
|
|
798
|
+
expandLevel,
|
|
799
|
+
}: {
|
|
800
|
+
data: unknown;
|
|
801
|
+
name?: string;
|
|
802
|
+
expandLevel: number;
|
|
803
|
+
}) {
|
|
804
|
+
const outerRef = useRef<HTMLDivElement>(null);
|
|
805
|
+
const shouldExpand = useMemo(
|
|
806
|
+
() => (level: number) => level < expandLevel,
|
|
807
|
+
[expandLevel]
|
|
808
|
+
);
|
|
809
|
+
return (
|
|
810
|
+
<div
|
|
811
|
+
ref={outerRef}
|
|
812
|
+
className={CLS.container}
|
|
813
|
+
role="tree"
|
|
814
|
+
aria-label="JSON view"
|
|
815
|
+
>
|
|
816
|
+
<DataRender
|
|
817
|
+
field={name}
|
|
818
|
+
value={data}
|
|
819
|
+
isLast
|
|
820
|
+
ctx={{ level: 0, shouldExpand, outerRef }}
|
|
821
|
+
/>
|
|
822
|
+
</div>
|
|
518
823
|
);
|
|
519
824
|
}
|
|
520
825
|
|
|
521
826
|
// ---------------------------------------------------------------------------
|
|
522
|
-
//
|
|
827
|
+
// Ref / typed-array collapsing (preprocessing before render)
|
|
523
828
|
// ---------------------------------------------------------------------------
|
|
524
829
|
|
|
525
830
|
/**
|
|
526
831
|
* Create a non-expandable wrapper that carries ref data as non-enumerable
|
|
527
|
-
* properties
|
|
528
|
-
*
|
|
832
|
+
* properties so the renderer can detect StreamRef/RunRef without exposing
|
|
833
|
+
* their internals as object fields.
|
|
529
834
|
*/
|
|
530
835
|
function makeOpaqueRef(ref: Record<string, unknown>): unknown {
|
|
531
836
|
const opaque = Object.create(null);
|
|
@@ -554,11 +859,11 @@ function makeBytesDisplay(display: FormattedStreamChunkDisplay): unknown {
|
|
|
554
859
|
|
|
555
860
|
/**
|
|
556
861
|
* Recursively walk data and replace RunRef/StreamRef/typed array objects with
|
|
557
|
-
* non-expandable versions so
|
|
862
|
+
* non-expandable versions so the renderer doesn't show their internals.
|
|
558
863
|
* Only recurses into plain objects and arrays to avoid stripping class
|
|
559
|
-
* instances (Date, Error, URL, Headers, etc.) that have their own rendering
|
|
560
|
-
*
|
|
561
|
-
*
|
|
864
|
+
* instances (Date, Error, URL, Headers, etc.) that have their own rendering.
|
|
865
|
+
* Map and Set containers are preserved while their contents are prepared for
|
|
866
|
+
* display.
|
|
562
867
|
*
|
|
563
868
|
* Exported for testing the typed-array detection path used by hydrated
|
|
564
869
|
* AI agent stream chunks (e.g. `{ delta: new Uint8Array(...) }`).
|
|
@@ -592,10 +897,14 @@ export function collapseRefs(data: unknown): unknown {
|
|
|
592
897
|
return result;
|
|
593
898
|
}
|
|
594
899
|
|
|
900
|
+
// ---------------------------------------------------------------------------
|
|
901
|
+
// Public component
|
|
902
|
+
// ---------------------------------------------------------------------------
|
|
903
|
+
|
|
595
904
|
export interface DataInspectorProps {
|
|
596
905
|
/** The data to inspect */
|
|
597
906
|
data: unknown;
|
|
598
|
-
/**
|
|
907
|
+
/** Levels strictly below this number auto-expand (default: 2) */
|
|
599
908
|
expandLevel?: number;
|
|
600
909
|
/** Optional name for the root node */
|
|
601
910
|
name?: string;
|
|
@@ -620,59 +929,47 @@ export function DataInspector({
|
|
|
620
929
|
}: DataInspectorProps) {
|
|
621
930
|
const collapsedData = useMemo(() => collapseRefs(data), [data]);
|
|
622
931
|
const stableData = useStableInspectorData(collapsedData);
|
|
623
|
-
const [initialExpandLevel, setInitialExpandLevel] = useState(expandLevel);
|
|
624
|
-
const isDark = useDarkMode();
|
|
625
|
-
const extendedTheme = isDark
|
|
626
|
-
? inspectorThemeExtendedDark
|
|
627
|
-
: inspectorThemeExtendedLight;
|
|
628
|
-
|
|
629
|
-
useEffect(() => {
|
|
630
|
-
// react-inspector reapplies expandLevel on every data change, which can
|
|
631
|
-
// reopen paths the user manually collapsed. Apply it only on mount.
|
|
632
|
-
setInitialExpandLevel(0);
|
|
633
|
-
}, []);
|
|
634
|
-
|
|
635
|
-
const content = (
|
|
636
|
-
<ExtendedThemeContext.Provider value={extendedTheme}>
|
|
637
|
-
<ObjectInspector
|
|
638
|
-
data={stableData}
|
|
639
|
-
name={name}
|
|
640
|
-
// @ts-expect-error react-inspector accepts theme objects at runtime despite
|
|
641
|
-
// types declaring string only — see https://github.com/storybookjs/react-inspector/blob/main/README.md#theme
|
|
642
|
-
theme={isDark ? inspectorThemeDark : inspectorThemeLight}
|
|
643
|
-
expandLevel={initialExpandLevel}
|
|
644
|
-
nodeRenderer={NodeRenderer}
|
|
645
|
-
/>
|
|
646
|
-
</ExtendedThemeContext.Provider>
|
|
647
|
-
);
|
|
648
932
|
|
|
649
|
-
let
|
|
933
|
+
let content: ReactNode = (
|
|
934
|
+
<>
|
|
935
|
+
{/* React 19 hoists & dedupes this <style> by href, so it is emitted once
|
|
936
|
+
regardless of how many inspectors are mounted. */}
|
|
937
|
+
<style href="wf-json-view" precedence="default">
|
|
938
|
+
{JSON_VIEW_STYLES}
|
|
939
|
+
</style>
|
|
940
|
+
<JsonTree data={stableData} name={name} expandLevel={expandLevel} />
|
|
941
|
+
</>
|
|
942
|
+
);
|
|
650
943
|
|
|
651
944
|
if (onStreamClick) {
|
|
652
|
-
|
|
945
|
+
content = (
|
|
653
946
|
<StreamClickContext.Provider value={onStreamClick}>
|
|
654
|
-
{
|
|
947
|
+
{content}
|
|
655
948
|
</StreamClickContext.Provider>
|
|
656
949
|
);
|
|
657
950
|
}
|
|
658
951
|
if (onRunClick) {
|
|
659
|
-
|
|
952
|
+
content = (
|
|
660
953
|
<RunClickContext.Provider value={onRunClick}>
|
|
661
|
-
{
|
|
954
|
+
{content}
|
|
662
955
|
</RunClickContext.Provider>
|
|
663
956
|
);
|
|
664
957
|
}
|
|
665
958
|
if (onDecrypt) {
|
|
666
|
-
|
|
959
|
+
content = (
|
|
667
960
|
<DecryptClickContext.Provider value={{ onDecrypt, isDecrypting }}>
|
|
668
|
-
{
|
|
961
|
+
{content}
|
|
669
962
|
</DecryptClickContext.Provider>
|
|
670
963
|
);
|
|
671
964
|
}
|
|
672
965
|
|
|
673
|
-
return
|
|
966
|
+
return content;
|
|
674
967
|
}
|
|
675
968
|
|
|
969
|
+
// ---------------------------------------------------------------------------
|
|
970
|
+
// Render stabilization (avoid re-renders when data is deeply equal)
|
|
971
|
+
// ---------------------------------------------------------------------------
|
|
972
|
+
|
|
676
973
|
function useStableInspectorData<T>(next: T): T {
|
|
677
974
|
const previousRef = useRef<T>(next);
|
|
678
975
|
if (!isDeepEqual(previousRef.current, next)) {
|