@workflow/web-shared 5.0.0-beta.2 → 5.0.0-beta.21
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/dist/components/error-boundary.js +1 -1
- package/dist/components/event-list-view.d.ts +16 -1
- package/dist/components/event-list-view.d.ts.map +1 -1
- package/dist/components/event-list-view.js +196 -85
- package/dist/components/hook-actions.js +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -1
- package/dist/components/new-trace-viewer/components/copy-button.d.ts +9 -0
- package/dist/components/new-trace-viewer/components/copy-button.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/copy-button.js +27 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts +10 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/event-list.js +46 -0
- 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/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 +15 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/split-pane.js +105 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts +36 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.js +254 -0
- package/dist/components/new-trace-viewer/components/timeline.module.css +46 -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 +19 -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 +15 -0
- package/dist/components/new-trace-viewer/context.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/context.js +47 -0
- package/dist/components/new-trace-viewer/icons.d.ts +6 -0
- package/dist/components/new-trace-viewer/icons.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/icons.js +15 -0
- 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 +11 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/trace-viewer.js +462 -0
- package/dist/components/new-trace-viewer/types.d.ts +3 -0
- package/dist/components/new-trace-viewer/types.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/types.js +2 -0
- package/dist/components/new-trace-viewer/utils.d.ts +61 -0
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/utils.js +345 -0
- package/dist/components/run-trace-view.js +1 -1
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +129 -102
- package/dist/components/sidebar/attributes-block.d.ts +28 -0
- package/dist/components/sidebar/attributes-block.d.ts.map +1 -0
- package/dist/components/sidebar/attributes-block.js +81 -0
- package/dist/components/sidebar/conversation-view.js +1 -1
- package/dist/components/sidebar/copyable-data-block.d.ts +1 -0
- package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
- package/dist/components/sidebar/copyable-data-block.js +16 -15
- package/dist/components/sidebar/detail-card.d.ts +5 -6
- package/dist/components/sidebar/detail-card.d.ts.map +1 -1
- package/dist/components/sidebar/detail-card.js +32 -16
- package/dist/components/sidebar/entity-detail-panel.d.ts +1 -3
- package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
- package/dist/components/sidebar/entity-detail-panel.js +17 -35
- package/dist/components/sidebar/events-list.d.ts +3 -1
- package/dist/components/sidebar/events-list.d.ts.map +1 -1
- package/dist/components/sidebar/events-list.js +36 -22
- package/dist/components/sidebar/resolve-hook-modal.js +1 -1
- package/dist/components/sidebar/sidebar-data-context.d.ts +29 -0
- package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar-data-context.js +19 -0
- package/dist/components/sidebar/span-detail-merge.d.ts +16 -0
- package/dist/components/sidebar/span-detail-merge.d.ts.map +1 -0
- package/dist/components/sidebar/span-detail-merge.js +53 -0
- package/dist/components/stream-viewer.d.ts +1 -1
- package/dist/components/stream-viewer.d.ts.map +1 -1
- package/dist/components/stream-viewer.js +3 -27
- 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.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 +14 -0
- package/dist/components/trace-viewer-new.d.ts.map +1 -0
- package/dist/components/trace-viewer-new.js +21 -0
- package/dist/components/ui/alert.js +1 -1
- 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 +1 -1
- 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 +22 -0
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +103 -13
- package/dist/components/ui/decrypt-button.js +1 -1
- package/dist/components/ui/error-card.js +1 -1
- 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/inspector-theme.d.ts +9 -10
- package/dist/components/ui/inspector-theme.d.ts.map +1 -1
- package/dist/components/ui/inspector-theme.js +39 -72
- package/dist/components/ui/kbd.d.ts +6 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/kbd.js +6 -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 +1 -1
- 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 +1 -3
- package/dist/components/workflow-trace-view.d.ts.map +1 -1
- package/dist/components/workflow-trace-view.js +11 -13
- package/dist/components/workflow-traces/event-colors.d.ts +1 -0
- package/dist/components/workflow-traces/event-colors.d.ts.map +1 -1
- package/dist/components/workflow-traces/event-colors.js +12 -1
- package/dist/components/workflow-traces/trace-colors.js +1 -1
- package/dist/components/workflow-traces/trace-span-construction.d.ts +2 -2
- package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +19 -5
- 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 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/lib/event-analysis.js +1 -1
- package/dist/lib/event-materialization.js +1 -1
- 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 +6 -0
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +154 -2
- package/dist/lib/stream-display.d.ts +18 -0
- package/dist/lib/stream-display.d.ts.map +1 -0
- package/dist/lib/stream-display.js +30 -0
- package/dist/lib/toast.js +1 -1
- package/dist/lib/trace-builder.d.ts +15 -0
- package/dist/lib/trace-builder.d.ts.map +1 -1
- package/dist/lib/trace-builder.js +29 -3
- package/dist/lib/utils.d.ts +20 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +74 -31
- 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 +484 -1
- package/package.json +10 -5
- package/src/components/event-list-view.tsx +279 -104
- package/src/components/index.ts +7 -0
- package/src/components/new-trace-viewer/components/copy-button.tsx +68 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +136 -0
- 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/span-markers.tsx +173 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +198 -0
- package/src/components/new-trace-viewer/components/timeline.module.css +46 -0
- package/src/components/new-trace-viewer/components/timeline.tsx +744 -0
- package/src/components/new-trace-viewer/components/trace-viewer-skeleton.tsx +94 -0
- package/src/components/new-trace-viewer/components/use-row-window.ts +140 -0
- package/src/components/new-trace-viewer/context.tsx +90 -0
- package/src/components/new-trace-viewer/icons.tsx +79 -0
- package/src/components/new-trace-viewer/search.ts +178 -0
- package/src/components/new-trace-viewer/trace-viewer.tsx +843 -0
- package/src/components/new-trace-viewer/types.ts +2 -0
- package/src/components/new-trace-viewer/utils.test.ts +182 -0
- package/src/components/new-trace-viewer/utils.ts +519 -0
- package/src/components/sidebar/attribute-panel.tsx +194 -240
- package/src/components/sidebar/attributes-block.tsx +173 -0
- package/src/components/sidebar/copyable-data-block.tsx +49 -27
- package/src/components/sidebar/detail-card.tsx +119 -59
- package/src/components/sidebar/entity-detail-panel.tsx +55 -111
- package/src/components/sidebar/events-list.tsx +85 -96
- package/src/components/sidebar/sidebar-data-context.tsx +62 -0
- package/src/components/sidebar/span-detail-merge.ts +65 -0
- package/src/components/stream-viewer.tsx +18 -40
- 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 +55 -0
- package/src/components/ui/button.tsx +68 -0
- package/src/components/ui/context-card.tsx +784 -0
- package/src/components/ui/data-inspector.tsx +244 -22
- package/src/components/ui/error-stack-block.tsx +84 -55
- package/src/components/ui/icon-button.tsx +53 -0
- package/src/components/ui/inspector-theme.ts +39 -81
- package/src/components/ui/kbd.tsx +21 -0
- package/src/components/ui/timestamp-tooltip.tsx +132 -194
- package/src/components/ui/tooltip.tsx +47 -0
- package/src/components/workflow-trace-view.tsx +19 -15
- package/src/components/workflow-traces/event-colors.ts +12 -0
- package/src/components/workflow-traces/trace-span-construction.ts +24 -5
- 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/exact-event-search-id.ts +67 -0
- package/src/lib/hydration.ts +166 -1
- package/src/lib/stream-display.ts +48 -0
- package/src/lib/trace-builder.ts +34 -2
- package/src/lib/utils.ts +83 -31
- package/src/lib/zstd-browser-decoder.ts +42 -0
- package/src/styles.css +484 -1
- 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/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.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/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/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.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/toast.js.map +0 -1
- package/dist/lib/trace-builder.js.map +0 -1
- package/dist/lib/utils.js.map +0 -1
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared theme configuration for react-inspector's ObjectInspector.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* - null:
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - functions (special): cyan
|
|
12
|
-
* - date: magenta
|
|
4
|
+
* Colors follow Geist's Shiki JSON palette so the inspector reads the same
|
|
5
|
+
* as highlighted code blocks across the product:
|
|
6
|
+
* - property names / punctuation: --ds-gray-1000 (default foreground)
|
|
7
|
+
* - strings / numbers / booleans: --ds-green-900
|
|
8
|
+
* - null / undefined: --ds-gray-900 (muted)
|
|
9
|
+
* - regexp / function: --ds-purple-900
|
|
10
|
+
* - date: --ds-pink-900
|
|
13
11
|
*
|
|
14
|
-
*
|
|
12
|
+
* Because the `--ds-*` tokens adapt to theme automatically, the light and
|
|
13
|
+
* dark objects are intentionally identical.
|
|
15
14
|
*/
|
|
16
15
|
|
|
17
16
|
// ---------------------------------------------------------------------------
|
|
@@ -25,11 +24,11 @@ export interface InspectorThemeExtended {
|
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
export const inspectorThemeExtendedLight: InspectorThemeExtended = {
|
|
28
|
-
OBJECT_VALUE_DATE_COLOR: '
|
|
27
|
+
OBJECT_VALUE_DATE_COLOR: 'var(--ds-pink-900)',
|
|
29
28
|
};
|
|
30
29
|
|
|
31
30
|
export const inspectorThemeExtendedDark: InspectorThemeExtended = {
|
|
32
|
-
OBJECT_VALUE_DATE_COLOR: '
|
|
31
|
+
OBJECT_VALUE_DATE_COLOR: 'var(--ds-pink-900)',
|
|
33
32
|
};
|
|
34
33
|
|
|
35
34
|
// ---------------------------------------------------------------------------
|
|
@@ -57,96 +56,55 @@ const shared = {
|
|
|
57
56
|
// Light theme
|
|
58
57
|
// ---------------------------------------------------------------------------
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
const geistTheme = {
|
|
61
60
|
...shared,
|
|
62
61
|
|
|
63
62
|
// Base text
|
|
64
63
|
BASE_COLOR: 'var(--ds-gray-1000)',
|
|
65
64
|
|
|
66
|
-
// Property names —
|
|
67
|
-
OBJECT_NAME_COLOR: 'var(--ds-gray-
|
|
65
|
+
// Property names — default foreground (matches JSON key color in Geist Shiki)
|
|
66
|
+
OBJECT_NAME_COLOR: 'var(--ds-gray-1000)',
|
|
68
67
|
|
|
69
|
-
// Strings & symbols — green
|
|
70
|
-
OBJECT_VALUE_STRING_COLOR: '
|
|
71
|
-
OBJECT_VALUE_SYMBOL_COLOR: '
|
|
68
|
+
// Strings & symbols — green
|
|
69
|
+
OBJECT_VALUE_STRING_COLOR: 'var(--ds-green-900)',
|
|
70
|
+
OBJECT_VALUE_SYMBOL_COLOR: 'var(--ds-green-900)',
|
|
72
71
|
|
|
73
|
-
// Numbers & booleans —
|
|
74
|
-
OBJECT_VALUE_NUMBER_COLOR: '
|
|
75
|
-
OBJECT_VALUE_BOOLEAN_COLOR: '
|
|
72
|
+
// Numbers & booleans — green (Geist JSON tokens)
|
|
73
|
+
OBJECT_VALUE_NUMBER_COLOR: 'var(--ds-green-900)',
|
|
74
|
+
OBJECT_VALUE_BOOLEAN_COLOR: 'var(--ds-green-900)',
|
|
76
75
|
|
|
77
|
-
// null —
|
|
76
|
+
// null — muted foreground
|
|
78
77
|
OBJECT_VALUE_NULL_COLOR: 'var(--ds-gray-900)',
|
|
79
78
|
|
|
80
|
-
// undefined —
|
|
81
|
-
OBJECT_VALUE_UNDEFINED_COLOR: 'var(--ds-gray-
|
|
79
|
+
// undefined — muted foreground
|
|
80
|
+
OBJECT_VALUE_UNDEFINED_COLOR: 'var(--ds-gray-900)',
|
|
82
81
|
|
|
83
|
-
// RegExp —
|
|
84
|
-
OBJECT_VALUE_REGEXP_COLOR: '
|
|
82
|
+
// RegExp — purple
|
|
83
|
+
OBJECT_VALUE_REGEXP_COLOR: 'var(--ds-purple-900)',
|
|
85
84
|
|
|
86
|
-
// Functions —
|
|
87
|
-
OBJECT_VALUE_FUNCTION_PREFIX_COLOR: '
|
|
85
|
+
// Functions — purple
|
|
86
|
+
OBJECT_VALUE_FUNCTION_PREFIX_COLOR: 'var(--ds-purple-900)',
|
|
88
87
|
|
|
89
|
-
// HTML (
|
|
90
|
-
HTML_TAG_COLOR: 'var(--ds-gray-
|
|
91
|
-
HTML_TAGNAME_COLOR: '
|
|
92
|
-
HTML_ATTRIBUTE_NAME_COLOR: '
|
|
93
|
-
HTML_ATTRIBUTE_VALUE_COLOR: '
|
|
94
|
-
HTML_COMMENT_COLOR: 'var(--ds-gray-
|
|
95
|
-
HTML_DOCTYPE_COLOR: 'var(--ds-gray-
|
|
88
|
+
// HTML (rarely used here, kept consistent with the palette)
|
|
89
|
+
HTML_TAG_COLOR: 'var(--ds-gray-900)',
|
|
90
|
+
HTML_TAGNAME_COLOR: 'var(--ds-blue-900)',
|
|
91
|
+
HTML_ATTRIBUTE_NAME_COLOR: 'var(--ds-amber-900)',
|
|
92
|
+
HTML_ATTRIBUTE_VALUE_COLOR: 'var(--ds-green-900)',
|
|
93
|
+
HTML_COMMENT_COLOR: 'var(--ds-gray-700)',
|
|
94
|
+
HTML_DOCTYPE_COLOR: 'var(--ds-gray-700)',
|
|
96
95
|
|
|
97
96
|
// Structural
|
|
98
|
-
ARROW_COLOR: 'var(--ds-gray-
|
|
97
|
+
ARROW_COLOR: 'var(--ds-gray-700)',
|
|
99
98
|
TABLE_BORDER_COLOR: 'var(--ds-gray-300)',
|
|
100
99
|
TABLE_TH_BACKGROUND_COLOR: 'var(--ds-gray-100)',
|
|
101
100
|
TABLE_TH_HOVER_COLOR: 'var(--ds-gray-200)',
|
|
102
|
-
TABLE_SORT_ICON_COLOR: 'var(--ds-gray-
|
|
101
|
+
TABLE_SORT_ICON_COLOR: 'var(--ds-gray-700)',
|
|
103
102
|
};
|
|
104
103
|
|
|
104
|
+
export const inspectorThemeLight = geistTheme;
|
|
105
|
+
|
|
105
106
|
// ---------------------------------------------------------------------------
|
|
106
107
|
// Dark theme
|
|
107
108
|
// ---------------------------------------------------------------------------
|
|
108
109
|
|
|
109
|
-
export const inspectorThemeDark =
|
|
110
|
-
...shared,
|
|
111
|
-
|
|
112
|
-
// Base text
|
|
113
|
-
BASE_COLOR: 'var(--ds-gray-1000)',
|
|
114
|
-
|
|
115
|
-
// Property names — white/light foreground (Node: unstyled = white in dark terminal)
|
|
116
|
-
OBJECT_NAME_COLOR: 'var(--ds-gray-900)',
|
|
117
|
-
|
|
118
|
-
// Strings & symbols — green (Node: 'green')
|
|
119
|
-
OBJECT_VALUE_STRING_COLOR: '#4ade80', // green-400
|
|
120
|
-
OBJECT_VALUE_SYMBOL_COLOR: '#4ade80',
|
|
121
|
-
|
|
122
|
-
// Numbers & booleans — yellow (Node: 'yellow')
|
|
123
|
-
OBJECT_VALUE_NUMBER_COLOR: '#facc15', // yellow-400
|
|
124
|
-
OBJECT_VALUE_BOOLEAN_COLOR: '#facc15',
|
|
125
|
-
|
|
126
|
-
// null — bold foreground / white (Node: 'bold')
|
|
127
|
-
OBJECT_VALUE_NULL_COLOR: 'var(--ds-gray-1000)',
|
|
128
|
-
|
|
129
|
-
// undefined — grey (Node: 'grey')
|
|
130
|
-
OBJECT_VALUE_UNDEFINED_COLOR: 'var(--ds-gray-500)',
|
|
131
|
-
|
|
132
|
-
// RegExp — red (Node regexp palette)
|
|
133
|
-
OBJECT_VALUE_REGEXP_COLOR: '#f87171', // red-400
|
|
134
|
-
|
|
135
|
-
// Functions — cyan (Node: 'special' → 'cyan')
|
|
136
|
-
OBJECT_VALUE_FUNCTION_PREFIX_COLOR: '#22d3ee', // cyan-400
|
|
137
|
-
|
|
138
|
-
// HTML
|
|
139
|
-
HTML_TAG_COLOR: 'var(--ds-gray-500)',
|
|
140
|
-
HTML_TAGNAME_COLOR: '#22d3ee',
|
|
141
|
-
HTML_ATTRIBUTE_NAME_COLOR: '#facc15',
|
|
142
|
-
HTML_ATTRIBUTE_VALUE_COLOR: '#4ade80',
|
|
143
|
-
HTML_COMMENT_COLOR: 'var(--ds-gray-500)',
|
|
144
|
-
HTML_DOCTYPE_COLOR: 'var(--ds-gray-500)',
|
|
145
|
-
|
|
146
|
-
// Structural
|
|
147
|
-
ARROW_COLOR: 'var(--ds-gray-500)',
|
|
148
|
-
TABLE_BORDER_COLOR: 'var(--ds-gray-300)',
|
|
149
|
-
TABLE_TH_BACKGROUND_COLOR: 'var(--ds-gray-100)',
|
|
150
|
-
TABLE_TH_HOVER_COLOR: 'var(--ds-gray-200)',
|
|
151
|
-
TABLE_SORT_ICON_COLOR: 'var(--ds-gray-500)',
|
|
152
|
-
};
|
|
110
|
+
export const inspectorThemeDark = geistTheme;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { cn } from '../../lib/utils';
|
|
3
|
+
|
|
4
|
+
export function Kbd({
|
|
5
|
+
children,
|
|
6
|
+
className,
|
|
7
|
+
}: {
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
}): ReactNode {
|
|
11
|
+
return (
|
|
12
|
+
<kbd
|
|
13
|
+
className={cn(
|
|
14
|
+
'inline-flex h-5 min-w-5 items-center justify-center rounded bg-background-100/20 px-1 text-center font-sans text-xs leading-none',
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
>
|
|
18
|
+
{children}
|
|
19
|
+
</kbd>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import type { ReactNode } from 'react';
|
|
4
|
-
import { useEffect,
|
|
5
|
-
import {
|
|
4
|
+
import { useEffect, useState } from 'react';
|
|
5
|
+
import {
|
|
6
|
+
ContextCardProvider,
|
|
7
|
+
ContextCardTrigger,
|
|
8
|
+
type ContextCardTriggerProps,
|
|
9
|
+
useHasContextCardProvider,
|
|
10
|
+
} from './context-card';
|
|
6
11
|
|
|
7
12
|
// ---------------------------------------------------------------------------
|
|
8
13
|
// Time formatting helpers
|
|
9
14
|
// ---------------------------------------------------------------------------
|
|
10
15
|
|
|
11
16
|
interface TimeUnit {
|
|
12
|
-
unit:
|
|
17
|
+
unit: Intl.RelativeTimeFormatUnit;
|
|
13
18
|
ms: number;
|
|
14
19
|
}
|
|
15
20
|
|
|
@@ -38,25 +43,69 @@ function formatTimeDifference(diff: number): string {
|
|
|
38
43
|
return result.join(', ');
|
|
39
44
|
}
|
|
40
45
|
|
|
41
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Detailed relative time string that auto-updates every second
|
|
48
|
+
* (e.g. "2 hours, 15 minutes, 30 seconds ago"). Used inside the hover card.
|
|
49
|
+
*/
|
|
50
|
+
export function useTimeAgo(date: number): string {
|
|
42
51
|
const [timeAgo, setTimeAgo] = useState<string>('');
|
|
43
52
|
|
|
44
53
|
useEffect(() => {
|
|
45
|
-
const
|
|
54
|
+
const updateTimeAgo = (): void => {
|
|
46
55
|
const diff = Date.now() - date;
|
|
47
|
-
const
|
|
48
|
-
setTimeAgo(
|
|
56
|
+
const formattedDiff = formatTimeDifference(diff);
|
|
57
|
+
setTimeAgo(formattedDiff ? `${formattedDiff} ago` : 'Just now');
|
|
49
58
|
};
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
|
|
60
|
+
updateTimeAgo();
|
|
61
|
+
const timer = setInterval(updateTimeAgo, 1000);
|
|
52
62
|
return () => clearInterval(timer);
|
|
53
63
|
}, [date]);
|
|
54
64
|
|
|
55
65
|
return timeAgo;
|
|
56
66
|
}
|
|
57
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Short relative time string that auto-updates every minute
|
|
70
|
+
* (e.g. "3 days ago", "5 hours ago"). Returns an empty string if `date` is
|
|
71
|
+
* nullish.
|
|
72
|
+
*/
|
|
73
|
+
export function useShortTimeAgo(date: number | null | undefined): string {
|
|
74
|
+
const [shortTimeAgo, setShortTimeAgo] = useState<string>('');
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (!date) {
|
|
78
|
+
setShortTimeAgo('');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const updateShortTimeAgo = (): void => {
|
|
83
|
+
const diff = Date.now() - date;
|
|
84
|
+
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
85
|
+
const hours = Math.floor(diff / (1000 * 60 * 60));
|
|
86
|
+
const minutes = Math.floor(diff / (1000 * 60));
|
|
87
|
+
|
|
88
|
+
if (days > 0) {
|
|
89
|
+
setShortTimeAgo(`${days} day${days > 1 ? 's' : ''} ago`);
|
|
90
|
+
} else if (hours > 0) {
|
|
91
|
+
setShortTimeAgo(`${hours} hour${hours > 1 ? 's' : ''} ago`);
|
|
92
|
+
} else if (minutes > 0) {
|
|
93
|
+
setShortTimeAgo(`${minutes} minute${minutes > 1 ? 's' : ''} ago`);
|
|
94
|
+
} else {
|
|
95
|
+
setShortTimeAgo('Just now');
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
updateShortTimeAgo();
|
|
100
|
+
const timer = setInterval(updateShortTimeAgo, 60000);
|
|
101
|
+
return () => clearInterval(timer);
|
|
102
|
+
}, [date]);
|
|
103
|
+
|
|
104
|
+
return shortTimeAgo;
|
|
105
|
+
}
|
|
106
|
+
|
|
58
107
|
// ---------------------------------------------------------------------------
|
|
59
|
-
//
|
|
108
|
+
// Hover card content
|
|
60
109
|
// ---------------------------------------------------------------------------
|
|
61
110
|
|
|
62
111
|
function ZoneDateTimeRow({
|
|
@@ -91,86 +140,34 @@ function ZoneDateTimeRow({
|
|
|
91
140
|
});
|
|
92
141
|
|
|
93
142
|
return (
|
|
94
|
-
<div
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}}
|
|
101
|
-
>
|
|
102
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
103
|
-
<div
|
|
104
|
-
style={{
|
|
105
|
-
display: 'inline-flex',
|
|
106
|
-
alignItems: 'center',
|
|
107
|
-
justifyContent: 'center',
|
|
108
|
-
height: 16,
|
|
109
|
-
padding: '0 6px',
|
|
110
|
-
backgroundColor: 'var(--ds-gray-200)',
|
|
111
|
-
borderRadius: 3,
|
|
112
|
-
fontSize: 11,
|
|
113
|
-
fontFamily: 'var(--font-mono, monospace)',
|
|
114
|
-
fontWeight: 500,
|
|
115
|
-
color: 'var(--ds-gray-900)',
|
|
116
|
-
whiteSpace: 'nowrap',
|
|
117
|
-
}}
|
|
118
|
-
>
|
|
119
|
-
{formattedZone}
|
|
143
|
+
<div className="flex items-center justify-between gap-3">
|
|
144
|
+
<div className="flex items-center gap-1.5">
|
|
145
|
+
<div className="flex items-center justify-center h-4 px-1.5 bg-gray-200 rounded-xs">
|
|
146
|
+
<span className="text-[12px] font-mono text-gray-900">
|
|
147
|
+
{formattedZone}
|
|
148
|
+
</span>
|
|
120
149
|
</div>
|
|
121
|
-
<span
|
|
122
|
-
style={{
|
|
123
|
-
fontSize: 13,
|
|
124
|
-
color: 'var(--ds-gray-1000)',
|
|
125
|
-
whiteSpace: 'nowrap',
|
|
126
|
-
}}
|
|
127
|
-
>
|
|
128
|
-
{formattedDate}
|
|
129
|
-
</span>
|
|
150
|
+
<span className="text-[13px] text-gray-1000">{formattedDate}</span>
|
|
130
151
|
</div>
|
|
131
|
-
<span
|
|
132
|
-
style={{
|
|
133
|
-
fontSize: 11,
|
|
134
|
-
fontFamily: 'var(--font-mono, monospace)',
|
|
135
|
-
fontVariantNumeric: 'tabular-nums',
|
|
136
|
-
color: 'var(--ds-gray-900)',
|
|
137
|
-
whiteSpace: 'nowrap',
|
|
138
|
-
}}
|
|
139
|
-
>
|
|
152
|
+
<span className="tabular-nums text-[12px] font-mono text-gray-900">
|
|
140
153
|
{formattedTime}
|
|
141
154
|
</span>
|
|
142
155
|
</div>
|
|
143
156
|
);
|
|
144
157
|
}
|
|
145
158
|
|
|
146
|
-
|
|
147
|
-
// Tooltip card content
|
|
148
|
-
// ---------------------------------------------------------------------------
|
|
149
|
-
|
|
150
|
-
function TimestampTooltipContent({ date }: { date: number }): ReactNode {
|
|
159
|
+
function RelativeTimeContextCardContent({ date }: { date: number }): ReactNode {
|
|
151
160
|
const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
152
161
|
const timeAgo = useTimeAgo(date);
|
|
153
162
|
|
|
154
163
|
return (
|
|
155
|
-
<div
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}}
|
|
163
|
-
>
|
|
164
|
-
<span
|
|
165
|
-
style={{
|
|
166
|
-
fontSize: 13,
|
|
167
|
-
fontVariantNumeric: 'tabular-nums',
|
|
168
|
-
color: 'var(--ds-gray-900)',
|
|
169
|
-
}}
|
|
170
|
-
>
|
|
171
|
-
{timeAgo}
|
|
172
|
-
</span>
|
|
173
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
|
164
|
+
<div className="flex flex-col gap-3 min-w-[300px]">
|
|
165
|
+
<div className="flex flex-col gap-3">
|
|
166
|
+
<span className="tabular-nums text-[13px] text-gray-900">
|
|
167
|
+
{timeAgo}
|
|
168
|
+
</span>
|
|
169
|
+
</div>
|
|
170
|
+
<div className="flex flex-col gap-2">
|
|
174
171
|
<ZoneDateTimeRow date={date} zone="UTC" />
|
|
175
172
|
<ZoneDateTimeRow date={date} zone={localTimezone} />
|
|
176
173
|
</div>
|
|
@@ -178,102 +175,75 @@ function TimestampTooltipContent({ date }: { date: number }): ReactNode {
|
|
|
178
175
|
);
|
|
179
176
|
}
|
|
180
177
|
|
|
178
|
+
function DefaultTimeText({
|
|
179
|
+
date,
|
|
180
|
+
}: {
|
|
181
|
+
date: number | null | undefined;
|
|
182
|
+
}): ReactNode {
|
|
183
|
+
const shortTimeAgo = useShortTimeAgo(date);
|
|
184
|
+
return <span className="text-label-14 text-gray-900">{shortTimeAgo}</span>;
|
|
185
|
+
}
|
|
186
|
+
|
|
181
187
|
// ---------------------------------------------------------------------------
|
|
182
|
-
//
|
|
188
|
+
// RelativeTimeCard
|
|
183
189
|
// ---------------------------------------------------------------------------
|
|
184
190
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
191
|
+
type RelativeTimeCardProps = Omit<
|
|
192
|
+
ContextCardTriggerProps,
|
|
193
|
+
'content' | 'children'
|
|
194
|
+
> & {
|
|
195
|
+
/** Timestamp in milliseconds to display as a relative time. */
|
|
196
|
+
date?: number | null;
|
|
197
|
+
/** Custom content to render instead of the default relative time text. */
|
|
198
|
+
children?: ReactNode;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Relative time label that reveals a context card with detailed UTC and local
|
|
203
|
+
* timestamps on hover. Renders a default short relative time label (e.g.
|
|
204
|
+
* "3 days ago") when `children` is omitted; renders just the children without
|
|
205
|
+
* the hover card when `date` is nullish.
|
|
206
|
+
*/
|
|
207
|
+
export function RelativeTimeCard({
|
|
192
208
|
date,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}): ReactNode {
|
|
199
|
-
const tooltipRef = useRef<HTMLDivElement>(null);
|
|
200
|
-
const [style, setStyle] = useState<React.CSSProperties>({
|
|
201
|
-
position: 'fixed',
|
|
202
|
-
zIndex: 9999,
|
|
203
|
-
visibility: 'hidden',
|
|
204
|
-
});
|
|
209
|
+
children: _children,
|
|
210
|
+
...props
|
|
211
|
+
}: RelativeTimeCardProps): ReactNode {
|
|
212
|
+
const children =
|
|
213
|
+
_children === undefined ? <DefaultTimeText date={date} /> : _children;
|
|
205
214
|
|
|
206
|
-
|
|
207
|
-
const placement = triggerRect.top > 240 ? 'above' : 'below';
|
|
208
|
-
const centerX = triggerRect.left + triggerRect.width / 2;
|
|
209
|
-
|
|
210
|
-
const el = tooltipRef.current;
|
|
211
|
-
const w = el ? el.offsetWidth : TOOLTIP_WIDTH;
|
|
212
|
-
const h = el ? el.offsetHeight : 100;
|
|
213
|
-
|
|
214
|
-
let left = centerX - w / 2;
|
|
215
|
-
left = Math.max(
|
|
216
|
-
VIEWPORT_PAD,
|
|
217
|
-
Math.min(left, window.innerWidth - w - VIEWPORT_PAD)
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
let top: number;
|
|
221
|
-
if (placement === 'above') {
|
|
222
|
-
top = triggerRect.top - h - 6;
|
|
223
|
-
if (top < VIEWPORT_PAD) {
|
|
224
|
-
top = triggerRect.bottom + 6;
|
|
225
|
-
}
|
|
226
|
-
} else {
|
|
227
|
-
top = triggerRect.bottom + 6;
|
|
228
|
-
if (top + h > window.innerHeight - VIEWPORT_PAD) {
|
|
229
|
-
top = triggerRect.top - h - 6;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
215
|
+
if (!date) return children;
|
|
232
216
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
zIndex: 9999,
|
|
238
|
-
borderRadius: 10,
|
|
239
|
-
border: '1px solid var(--ds-gray-alpha-200)',
|
|
240
|
-
backgroundColor: 'var(--ds-background-100)',
|
|
241
|
-
boxShadow: '0 4px 12px rgba(0,0,0,0.08), 0 1px 3px rgba(0,0,0,0.06)',
|
|
242
|
-
visibility: 'visible',
|
|
243
|
-
});
|
|
244
|
-
}, [triggerRect]);
|
|
245
|
-
|
|
246
|
-
return createPortal(
|
|
247
|
-
// biome-ignore lint/a11y/noStaticElementInteractions: tooltip hover zone
|
|
248
|
-
<div
|
|
249
|
-
ref={tooltipRef}
|
|
250
|
-
onMouseEnter={onMouseEnter}
|
|
251
|
-
onMouseLeave={onMouseLeave}
|
|
252
|
-
style={style}
|
|
217
|
+
return (
|
|
218
|
+
<ContextCardTrigger
|
|
219
|
+
content={<RelativeTimeContextCardContent date={date} />}
|
|
220
|
+
{...props}
|
|
253
221
|
>
|
|
254
|
-
|
|
255
|
-
</
|
|
256
|
-
document.body
|
|
222
|
+
{children}
|
|
223
|
+
</ContextCardTrigger>
|
|
257
224
|
);
|
|
258
225
|
}
|
|
259
226
|
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
// TimestampTooltip — convenience wrapper used across the observability UI
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Wraps an already-formatted timestamp display with a relative-time hover
|
|
233
|
+
* card. Self-mounts a {@link ContextCardProvider} when one isn't already
|
|
234
|
+
* present so it works anywhere, but shares a provider (enabling the animated
|
|
235
|
+
* card morph between adjacent timestamps) when rendered inside one.
|
|
236
|
+
*/
|
|
260
237
|
export function TimestampTooltip({
|
|
261
238
|
date,
|
|
262
239
|
children,
|
|
240
|
+
side = 'top',
|
|
263
241
|
}: {
|
|
264
242
|
date: number | Date | string | null | undefined;
|
|
265
243
|
children: ReactNode;
|
|
244
|
+
side?: ContextCardTriggerProps['side'];
|
|
266
245
|
}): ReactNode {
|
|
267
|
-
const
|
|
268
|
-
const [triggerRect, setTriggerRect] = useState<DOMRect | null>(null);
|
|
269
|
-
const triggerRef = useRef<HTMLSpanElement>(null);
|
|
270
|
-
const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
271
|
-
|
|
272
|
-
useEffect(() => {
|
|
273
|
-
return () => {
|
|
274
|
-
if (closeTimer.current) clearTimeout(closeTimer.current);
|
|
275
|
-
};
|
|
276
|
-
}, []);
|
|
246
|
+
const hasProvider = useHasContextCardProvider();
|
|
277
247
|
|
|
278
248
|
const ts =
|
|
279
249
|
date == null
|
|
@@ -284,43 +254,11 @@ export function TimestampTooltip({
|
|
|
284
254
|
|
|
285
255
|
if (ts == null || Number.isNaN(ts)) return <>{children}</>;
|
|
286
256
|
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
clearTimeout(closeTimer.current);
|
|
290
|
-
closeTimer.current = null;
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
const scheduleClose = () => {
|
|
295
|
-
cancelClose();
|
|
296
|
-
closeTimer.current = setTimeout(() => setOpen(false), 120);
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
const handleOpen = () => {
|
|
300
|
-
cancelClose();
|
|
301
|
-
if (triggerRef.current) {
|
|
302
|
-
setTriggerRect(triggerRef.current.getBoundingClientRect());
|
|
303
|
-
}
|
|
304
|
-
setOpen(true);
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
return (
|
|
308
|
-
// biome-ignore lint/a11y/noStaticElementInteractions: tooltip trigger
|
|
309
|
-
<span
|
|
310
|
-
ref={triggerRef}
|
|
311
|
-
onMouseEnter={handleOpen}
|
|
312
|
-
onMouseLeave={scheduleClose}
|
|
313
|
-
style={{ display: 'inline-flex' }}
|
|
314
|
-
>
|
|
257
|
+
const card = (
|
|
258
|
+
<RelativeTimeCard date={ts} side={side} asChild>
|
|
315
259
|
{children}
|
|
316
|
-
|
|
317
|
-
<TooltipPortal
|
|
318
|
-
triggerRect={triggerRect}
|
|
319
|
-
onMouseEnter={cancelClose}
|
|
320
|
-
onMouseLeave={scheduleClose}
|
|
321
|
-
date={ts}
|
|
322
|
-
/>
|
|
323
|
-
)}
|
|
324
|
-
</span>
|
|
260
|
+
</RelativeTimeCard>
|
|
325
261
|
);
|
|
262
|
+
|
|
263
|
+
return hasProvider ? card : <ContextCardProvider>{card}</ContextCardProvider>;
|
|
326
264
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { cn } from '../../lib/utils';
|
|
6
|
+
|
|
7
|
+
const TooltipProvider = TooltipPrimitive.Provider;
|
|
8
|
+
|
|
9
|
+
const Tooltip = TooltipPrimitive.Root;
|
|
10
|
+
|
|
11
|
+
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
12
|
+
|
|
13
|
+
const TooltipContent = React.forwardRef<
|
|
14
|
+
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
15
|
+
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & {
|
|
16
|
+
showArrow?: boolean;
|
|
17
|
+
}
|
|
18
|
+
>(
|
|
19
|
+
(
|
|
20
|
+
{ className, sideOffset = 8, showArrow = true, children, ...props },
|
|
21
|
+
ref
|
|
22
|
+
) => (
|
|
23
|
+
<TooltipPrimitive.Portal>
|
|
24
|
+
<TooltipPrimitive.Content
|
|
25
|
+
ref={ref}
|
|
26
|
+
sideOffset={sideOffset}
|
|
27
|
+
className={cn(
|
|
28
|
+
'z-[99999] flex items-center gap-1 rounded-[10px] bg-gray-1000 px-2 py-1.5 !text-label-13 text-background-100 shadow-md select-none',
|
|
29
|
+
className
|
|
30
|
+
)}
|
|
31
|
+
{...props}
|
|
32
|
+
>
|
|
33
|
+
{children}
|
|
34
|
+
{showArrow ? (
|
|
35
|
+
<TooltipPrimitive.Arrow
|
|
36
|
+
width={11}
|
|
37
|
+
height={5}
|
|
38
|
+
className="fill-gray-1000"
|
|
39
|
+
/>
|
|
40
|
+
) : null}
|
|
41
|
+
</TooltipPrimitive.Content>
|
|
42
|
+
</TooltipPrimitive.Portal>
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
46
|
+
|
|
47
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|