@workflow/web-shared 5.0.0-beta.11 → 5.0.0-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/components/event-list-view.d.ts.map +1 -1
  2. package/dist/components/event-list-view.js +9 -9
  3. package/dist/components/new-trace-viewer/components/event-list.d.ts +1 -1
  4. package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -1
  5. package/dist/components/new-trace-viewer/components/event-list.js +4 -2
  6. package/dist/components/new-trace-viewer/components/timeline.d.ts +1 -1
  7. package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -1
  8. package/dist/components/new-trace-viewer/components/timeline.js +4 -4
  9. package/dist/components/new-trace-viewer/context.d.ts +1 -1
  10. package/dist/components/new-trace-viewer/context.d.ts.map +1 -1
  11. package/dist/components/new-trace-viewer/context.js +1 -1
  12. package/dist/components/new-trace-viewer/icons.js +3 -3
  13. package/dist/components/new-trace-viewer/search.d.ts +1 -1
  14. package/dist/components/new-trace-viewer/search.d.ts.map +1 -1
  15. package/dist/components/new-trace-viewer/search.js +1 -1
  16. package/dist/components/new-trace-viewer/trace-viewer.d.ts +2 -2
  17. package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -1
  18. package/dist/components/new-trace-viewer/trace-viewer.js +7 -8
  19. package/dist/components/new-trace-viewer/types.d.ts +2 -0
  20. package/dist/components/new-trace-viewer/types.d.ts.map +1 -1
  21. package/dist/components/new-trace-viewer/types.js +2 -2
  22. package/dist/components/new-trace-viewer/utils.d.ts +1 -1
  23. package/dist/components/new-trace-viewer/utils.d.ts.map +1 -1
  24. package/dist/components/new-trace-viewer/utils.js +1 -1
  25. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  26. package/dist/components/sidebar/attribute-panel.js +7 -7
  27. package/dist/components/sidebar/events-list.d.ts.map +1 -1
  28. package/dist/components/sidebar/events-list.js +7 -7
  29. package/dist/components/trace-viewer-new.d.ts.map +1 -1
  30. package/dist/components/trace-viewer-new.js +2 -3
  31. package/dist/components/ui/error-stack-block.d.ts +17 -10
  32. package/dist/components/ui/error-stack-block.d.ts.map +1 -1
  33. package/dist/components/ui/error-stack-block.js +30 -19
  34. package/dist/lib/hydration.d.ts.map +1 -1
  35. package/dist/lib/hydration.js +26 -2
  36. package/package.json +4 -4
  37. package/src/components/event-list-view.tsx +12 -11
  38. package/src/components/new-trace-viewer/components/event-list.tsx +4 -3
  39. package/src/components/new-trace-viewer/components/timeline.tsx +4 -4
  40. package/src/components/new-trace-viewer/context.tsx +1 -1
  41. package/src/components/new-trace-viewer/icons.tsx +2 -2
  42. package/src/components/new-trace-viewer/search.ts +1 -1
  43. package/src/components/new-trace-viewer/trace-viewer.tsx +8 -15
  44. package/src/components/new-trace-viewer/types.ts +2 -0
  45. package/src/components/new-trace-viewer/utils.ts +1 -1
  46. package/src/components/sidebar/attribute-panel.tsx +6 -9
  47. package/src/components/sidebar/events-list.tsx +6 -9
  48. package/src/components/trace-viewer-new.tsx +2 -4
  49. package/src/components/ui/error-stack-block.tsx +51 -31
  50. package/src/lib/hydration.ts +28 -1
  51. package/dist/components/new-trace-viewer/detail-panel.d.ts +0 -10
  52. package/dist/components/new-trace-viewer/detail-panel.d.ts.map +0 -1
  53. package/dist/components/new-trace-viewer/detail-panel.js +0 -13
  54. package/dist/components/new-trace-viewer/util/constants.d.ts +0 -1
  55. package/dist/components/new-trace-viewer/util/constants.d.ts.map +0 -1
  56. package/dist/components/new-trace-viewer/util/constants.js +0 -2
  57. package/src/components/new-trace-viewer/detail-panel.tsx +0 -55
  58. package/src/components/new-trace-viewer/util/constants.ts +0 -0
@@ -26,8 +26,8 @@ import {
26
26
  EntityDetailPanel,
27
27
  type SelectedSpanInfo,
28
28
  } from '../sidebar/entity-detail-panel';
29
- import { useSidebarDataOptional } from '../sidebar/sidebar-data-context';
30
- import type { Trace } from '../trace-viewer/types';
29
+ import { useSidebarData } from '../sidebar/sidebar-data-context';
30
+ import type { TraceWithMeta } from './types';
31
31
  import { formatDuration, getHighResInMs } from '../trace-viewer/util/timing';
32
32
  import { IconButton } from '../ui/icon-button';
33
33
  import { Spinner } from '../ui/spinner';
@@ -46,12 +46,11 @@ import {
46
46
  TooltipTrigger,
47
47
  } from '../ui/tooltip';
48
48
  import { ActiveSpanProvider, useActiveSpan } from './context';
49
- import { DetailPanel } from './detail-panel';
50
49
  import { searchSpans } from './search';
51
50
  import { computeRootBounds, computeTimeMarkers } from './utils';
52
51
 
53
52
  interface NewTraceViewerProps {
54
- trace: Trace;
53
+ trace: TraceWithMeta;
55
54
  onLoadMore?: () => void | Promise<void>;
56
55
  hasMore?: boolean;
57
56
  isLoadingMore?: boolean;
@@ -141,10 +140,10 @@ function useAnimatedViewport(initial: Viewport) {
141
140
 
142
141
  function useSelectedSpanInfo(): SelectedSpanInfo | null {
143
142
  const { activeSpan } = useActiveSpan();
144
- const sidebar = useSidebarDataOptional();
143
+ const sidebar = useSidebarData();
145
144
 
146
145
  return useMemo(() => {
147
- if (!activeSpan || !sidebar) return null;
146
+ if (!activeSpan) return null;
148
147
 
149
148
  const correlationId = activeSpan.spanId;
150
149
  const rawEvents = correlationId
@@ -193,7 +192,7 @@ function NewTraceViewerContent({
193
192
  const { activeSpan, activeSpanId, setActiveSpan, clearActiveSpan } =
194
193
  useActiveSpan();
195
194
 
196
- const sidebar = useSidebarDataOptional();
195
+ const sidebar = useSidebarData();
197
196
  const selectedSpan = useSelectedSpanInfo();
198
197
 
199
198
  const [searchQuery, setSearchQuery] = useState('');
@@ -562,7 +561,7 @@ function NewTraceViewerContent({
562
561
  <div
563
562
  data-pane="pane-root"
564
563
  data-has-detail={activeSpan ? '' : undefined}
565
- className="grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,420px,100%)]"
564
+ className="grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,360px,100%)]"
566
565
  >
567
566
  <div
568
567
  id="trace-parent"
@@ -674,7 +673,7 @@ function NewTraceViewerContent({
674
673
  </div>
675
674
 
676
675
  {/* Detail panel */}
677
- {activeSpan && sidebar ? (
676
+ {activeSpan ? (
678
677
  <aside className="flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto">
679
678
  {/* Panel header */}
680
679
  <div className="flex items-center justify-between gap-2 shrink-0 px-4 pt-3 pb-3">
@@ -750,12 +749,6 @@ function NewTraceViewerContent({
750
749
  </ErrorBoundary>
751
750
  </div>
752
751
  </aside>
753
- ) : activeSpan ? (
754
- <DetailPanel
755
- span={activeSpan}
756
- rootStart={root.startTime}
757
- onClose={clearActiveSpan}
758
- />
759
752
  ) : null}
760
753
  </div>
761
754
  );
@@ -0,0 +1,2 @@
1
+ export type { Span, SpanEvent, Trace } from '../trace-viewer/types';
2
+ export type { TraceWithMeta } from '../../lib/trace-builder';
@@ -1,4 +1,4 @@
1
- import type { Span, SpanEvent } from '../trace-viewer/types';
1
+ import type { Span, SpanEvent } from './types';
2
2
  import { formatDuration, getHighResInMs } from '../trace-viewer/util/timing';
3
3
 
4
4
  // ---------------------------------------------------------------------------
@@ -8,20 +8,17 @@ import { useCallback, useContext, useMemo, useState } from 'react';
8
8
  import { isEncryptedMarker, isExpiredMarker } from '../../lib/hydration';
9
9
  import { useToast } from '../../lib/toast';
10
10
  import { extractConversation, isDoStreamStep } from '../../lib/utils';
11
+ import { CopyButton } from '../new-trace-viewer/components/copy-button';
12
+ import { MiddleTruncate } from '../new-trace-viewer/components/middle-truncate/middle-truncate';
11
13
  import {
12
14
  DecryptClickContext,
13
15
  RunClickContext,
14
16
  StreamClickContext,
15
17
  } from '../ui/data-inspector';
16
18
  import { ErrorCard } from '../ui/error-card';
17
- import {
18
- ErrorStackBlock,
19
- isStructuredErrorWithStack,
20
- } from '../ui/error-stack-block';
19
+ import { ErrorStackBlock, isStructuredError } from '../ui/error-stack-block';
21
20
  import { Skeleton } from '../ui/skeleton';
22
21
  import { TimestampTooltip } from '../ui/timestamp-tooltip';
23
- import { CopyButton } from '../new-trace-viewer/components/copy-button';
24
- import { MiddleTruncate } from '../new-trace-viewer/components/middle-truncate/middle-truncate';
25
22
  import { ConversationView } from './conversation-view';
26
23
  import { CopyableDataBlock, EncryptedDataBlock } from './copyable-data-block';
27
24
  import { DetailCard } from './detail-card';
@@ -548,9 +545,9 @@ const attributeToDisplayFn: Record<
548
545
  if (isExpiredMarker(value)) return <ExpiredFieldBlock />;
549
546
  if (!hasDisplayContent(value)) return null;
550
547
 
551
- // If the error object has a `stack` field, render it as readable
552
- // pre-formatted text. Otherwise fall back to the raw JSON viewer.
553
- if (isStructuredErrorWithStack(value)) {
548
+ // Structured workflow errors may be persisted as either `{ message }` or
549
+ // `{ message, stack }`. Render both with the dedicated error block.
550
+ if (isStructuredError(value)) {
554
551
  return (
555
552
  <DetailCard summary="Error" defaultOpen>
556
553
  <ErrorStackBlock value={value} />
@@ -4,10 +4,7 @@ import { EVENT_DATA_REF_FIELDS, type Event } from '@workflow/world';
4
4
  import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
5
5
  import { hasEncryptedFields, isExpiredMarker } from '../../lib/hydration';
6
6
  import { ErrorCard } from '../ui/error-card';
7
- import {
8
- ErrorStackBlock,
9
- isStructuredErrorWithStack,
10
- } from '../ui/error-stack-block';
7
+ import { ErrorStackBlock, isStructuredError } from '../ui/error-stack-block';
11
8
  import { Skeleton } from '../ui/skeleton';
12
9
  import { CopyableDataBlock, EncryptedDataBlock } from './copyable-data-block';
13
10
  import { DetailCard } from './detail-card';
@@ -196,8 +193,8 @@ function hasOnlyExpiredFields(data: unknown, eventType: string): boolean {
196
193
  }
197
194
 
198
195
  /**
199
- * Renders event data, using ErrorStackBlock for error events that contain
200
- * a structured error with a stack trace, and CopyableDataBlock otherwise.
196
+ * Renders event data, using ErrorStackBlock for error events that contain a
197
+ * structured error, and CopyableDataBlock otherwise.
201
198
  */
202
199
  function EventDataBlock({
203
200
  eventType,
@@ -239,12 +236,12 @@ function EventDataBlock({
239
236
  const record = data as Record<string, unknown>;
240
237
 
241
238
  // Check the nested `error` field first (the StructuredError)
242
- if (isStructuredErrorWithStack(record.error)) {
239
+ if (isStructuredError(record.error)) {
243
240
  return <ErrorStackBlock value={record.error} />;
244
241
  }
245
242
 
246
- // Some error formats put the stack at the top level of eventData
247
- if (isStructuredErrorWithStack(record)) {
243
+ // Some error formats put the message/stack at the top level of eventData.
244
+ if (isStructuredError(record)) {
248
245
  return <ErrorStackBlock value={record} />;
249
246
  }
250
247
  }
@@ -8,7 +8,6 @@ import {
8
8
  type SidebarDataContextValue,
9
9
  SidebarDataProvider,
10
10
  } from './sidebar/sidebar-data-context';
11
- import type { Trace } from './trace-viewer/types';
12
11
 
13
12
  const NewTraceViewer = ({
14
13
  run,
@@ -27,14 +26,13 @@ const NewTraceViewer = ({
27
26
  isLoadingMore?: boolean;
28
27
  loading?: boolean;
29
28
  }) => {
30
- const traceWithMeta: TraceWithMeta | undefined = useMemo(() => {
29
+ const trace: TraceWithMeta | undefined = useMemo(() => {
31
30
  if (!run?.runId) {
32
31
  return undefined;
33
32
  }
34
33
  return buildTrace(run, events, new Date());
35
34
  // eslint-disable-next-line react-hooks/exhaustive-deps -- `new Date()` is intentionally not a dep
36
35
  }, [run, events]);
37
- const trace = traceWithMeta;
38
36
 
39
37
  if (!trace || (loading && events.length === 0)) {
40
38
  return <TraceViewerSkeleton />;
@@ -44,7 +42,7 @@ const NewTraceViewer = ({
44
42
  <SidebarDataProvider value={sidebarData}>
45
43
  <div className="relative w-full h-full flex">
46
44
  <NewTraceViewerComponent
47
- trace={trace as Trace}
45
+ trace={trace}
48
46
  onLoadMore={onLoadMore}
49
47
  hasMore={hasMore}
50
48
  isLoadingMore={isLoadingMore}
@@ -3,18 +3,36 @@
3
3
  import { AlertCircle } from 'lucide-react';
4
4
  import { CopyButton } from '../new-trace-viewer/components/copy-button';
5
5
 
6
+ export type StructuredErrorRecord = Record<string, unknown> & {
7
+ message?: string;
8
+ stack?: string;
9
+ };
10
+
6
11
  /**
7
- * Check whether `value` looks like a structured error object with a `stack`
8
- * field that we can render as pre-formatted text.
12
+ * Check whether `value` looks like a structured error object we can render
13
+ * with the error block. Some persisted workflow errors only include a
14
+ * `message`, while runtime errors usually also include `stack`.
9
15
  */
10
- export function isStructuredErrorWithStack(
16
+ export function isStructuredError(
11
17
  value: unknown
12
- ): value is Record<string, unknown> & { stack: string } {
18
+ ): value is StructuredErrorRecord {
13
19
  return (
14
20
  value != null &&
15
21
  typeof value === 'object' &&
16
- 'stack' in value &&
17
- typeof (value as Record<string, unknown>).stack === 'string'
22
+ (typeof (value as Record<string, unknown>).message === 'string' ||
23
+ typeof (value as Record<string, unknown>).stack === 'string')
24
+ );
25
+ }
26
+
27
+ /**
28
+ * Narrower guard kept for callers that specifically need a stack trace.
29
+ */
30
+ export function isStructuredErrorWithStack(
31
+ value: unknown
32
+ ): value is StructuredErrorRecord & { stack: string } {
33
+ return (
34
+ isStructuredError(value) &&
35
+ typeof (value as StructuredErrorRecord).stack === 'string'
18
36
  );
19
37
  }
20
38
 
@@ -34,22 +52,22 @@ function deriveTitle(message: string): string {
34
52
  }
35
53
 
36
54
  /**
37
- * Renders an error with a `stack` field as a visually distinct error block.
38
- * Shows the error message with an alert icon at the top, separated from
39
- * the stack trace below.
55
+ * Renders a structured error as a visually distinct error block. Shows the
56
+ * error message with an alert icon at the top, separated from the stack trace
57
+ * or full message below.
40
58
  */
41
- export function ErrorStackBlock({
42
- value,
43
- }: {
44
- value: Record<string, unknown> & { stack: string };
45
- }) {
46
- const stack = value.stack;
59
+ export function ErrorStackBlock({ value }: { value: StructuredErrorRecord }) {
60
+ const stack = typeof value.stack === 'string' ? value.stack : undefined;
47
61
  const message = typeof value.message === 'string' ? value.message : undefined;
48
- // V8's `Error.stack` already starts with `Name: message`, so when the
49
- // body shows the stack it includes the full multi-line message anyway.
50
- // The header just needs the first line.
51
- const title = message ? deriveTitle(message) : undefined;
52
- const copyText = message ? `${message}\n\n${stack}` : stack;
62
+ const body = stack ?? message ?? '';
63
+ // V8's `Error.stack` already starts with `Name: message`; message-only
64
+ // errors use the message as the body so long single-line failures remain
65
+ // readable even when the header truncates.
66
+ const title = message ? deriveTitle(message) : deriveTitle(body);
67
+ const copyText =
68
+ message && stack && !stack.includes(message)
69
+ ? `${message}\n\n${stack}`
70
+ : body;
53
71
 
54
72
  return (
55
73
  <div
@@ -76,8 +94,8 @@ export function ErrorStackBlock({
76
94
  <AlertCircle className="h-4 w-4 shrink-0" />
77
95
  <p
78
96
  className="text-xs font-semibold m-0 truncate"
79
- // The full multi-line message is in the stack body below; the
80
- // header just shows the first line, single-line, with overflow
97
+ // The full message or stack is in the body below; the header just
98
+ // shows the first line, single-line, with overflow
81
99
  // ellipsised so a long title doesn't push the copy button or
82
100
  // wrap into the framed hint/docs lines.
83
101
  title={message}
@@ -86,15 +104,17 @@ export function ErrorStackBlock({
86
104
  </p>
87
105
  </div>
88
106
  )}
89
- <pre
90
- className="px-3 py-2.5 text-xs font-mono whitespace-pre-wrap break-words overflow-auto m-0"
91
- style={{
92
- color: 'var(--ds-red-900)',
93
- background: 'var(--ds-red-200)',
94
- }}
95
- >
96
- {stack}
97
- </pre>
107
+ {body && (
108
+ <pre
109
+ className="px-3 py-2.5 text-xs font-mono whitespace-pre-wrap break-words overflow-auto m-0"
110
+ style={{
111
+ color: 'var(--ds-red-900)',
112
+ background: 'var(--ds-red-200)',
113
+ }}
114
+ >
115
+ {body}
116
+ </pre>
117
+ )}
98
118
  </div>
99
119
  );
100
120
  }
@@ -135,7 +135,8 @@ export function getWebRevivers(): Revivers {
135
135
  // Error family. The reducer side (see
136
136
  // `packages/core/src/serialization/reducers/common.ts`) emits a tagged
137
137
  // entry for each built-in Error subclass plus the workflow-specific
138
- // `FatalError` / `RetryableError` and `AggregateError`. Without
138
+ // `FatalError` / `RetryableError` / `HookConflictError` /
139
+ // `RuntimeDecryptionError` and `AggregateError`. Without
139
140
  // matching revivers here, `devalue.unflatten` throws "Unknown type X"
140
141
  // — which surfaces in the web o11y UI as "Failed to load resource
141
142
  // details: Unknown type FatalError".
@@ -183,6 +184,20 @@ export function getWebRevivers(): Revivers {
183
184
  if (value.stack !== undefined) error.stack = value.stack;
184
185
  return error;
185
186
  },
187
+ HookConflictError: (value) => {
188
+ const opts = 'cause' in value ? { cause: value.cause } : undefined;
189
+ const error = new Error(value.message, opts) as Error & {
190
+ token?: string;
191
+ conflictingRunId?: string;
192
+ };
193
+ error.name = 'HookConflictError';
194
+ error.token = value.token;
195
+ if (value.conflictingRunId !== undefined) {
196
+ error.conflictingRunId = value.conflictingRunId;
197
+ }
198
+ if (value.stack !== undefined) error.stack = value.stack;
199
+ return error;
200
+ },
186
201
  RetryableError: (value) => {
187
202
  const opts = 'cause' in value ? { cause: value.cause } : undefined;
188
203
  const error = new Error(value.message, opts) as Error & {
@@ -201,6 +216,18 @@ export function getWebRevivers(): Revivers {
201
216
  }
202
217
  return error;
203
218
  },
219
+ RuntimeDecryptionError: (value) => {
220
+ const opts = 'cause' in value ? { cause: value.cause } : undefined;
221
+ const error = new Error(value.message, opts) as Error & {
222
+ context?: unknown;
223
+ };
224
+ error.name = 'RuntimeDecryptionError';
225
+ if (value.context !== undefined) {
226
+ error.context = value.context;
227
+ }
228
+ if (value.stack !== undefined) error.stack = value.stack;
229
+ return error;
230
+ },
204
231
  DOMException: (value) => {
205
232
  // Modern browsers and Node 18+ expose `DOMException` on globalThis.
206
233
  // `AbortController.abort()` with no argument synthesizes one as the
@@ -1,10 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- import type { Span } from '../trace-viewer/types';
3
- interface DetailPanelProps {
4
- span: Span;
5
- rootStart: number;
6
- onClose: () => void;
7
- }
8
- export declare function DetailPanel({ span, rootStart, onClose, }: DetailPanelProps): ReactNode;
9
- export {};
10
- //# sourceMappingURL=detail-panel.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"detail-panel.d.ts","sourceRoot":"","sources":["../../../src/components/new-trace-viewer/detail-panel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAKlD,UAAU,gBAAgB;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,SAAS,EACT,OAAO,GACR,EAAE,gBAAgB,GAAG,SAAS,CAmC9B"}
@@ -1,13 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { X } from 'lucide-react';
4
- import { formatDuration, getHighResInMs } from '../trace-viewer/util/timing';
5
- import { IconButton } from '../ui/icon-button';
6
- import { getSpanDurationMs } from './utils';
7
- export function DetailPanel({ span, rootStart, onClose, }) {
8
- const startMs = getHighResInMs(span.startTime);
9
- const durationMs = getSpanDurationMs(span);
10
- const offsetMs = startMs - rootStart;
11
- return (_jsxs("aside", { className: "grid h-full max-h-full grid-rows-[2.5rem_1fr] bg-background-200", children: [_jsxs("div", { className: "flex items-center justify-between px-3 border-b border-gray-alpha-400", children: [_jsx("span", { className: "text-sm font-medium text-gray-1000 truncate", children: span.name }), _jsx(IconButton, { "aria-label": "Close span details", onClick: onClose, children: _jsx(X, { className: "w-4 h-4" }) })] }), _jsx("div", { className: "overflow-y-auto p-3 space-y-3", children: _jsxs("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1.5 text-sm", children: [_jsx("dt", { className: "text-gray-900", children: "Resource" }), _jsx("dd", { className: "text-gray-1000 font-mono", children: span.resource }), _jsx("dt", { className: "text-gray-900", children: "Duration" }), _jsx("dd", { className: "text-gray-1000 tabular-nums font-mono", children: formatDuration(durationMs) }), _jsx("dt", { className: "text-gray-900", children: "Offset" }), _jsxs("dd", { className: "text-gray-1000 tabular-nums font-mono", children: ["+", formatDuration(offsetMs)] }), _jsx("dt", { className: "text-gray-900", children: "Status" }), _jsx("dd", { className: "text-gray-1000 font-mono", children: span.status.code === 2 ? 'Error' : 'OK' })] }) })] }));
12
- }
13
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV0YWlsLXBhbmVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvbmV3LXRyYWNlLXZpZXdlci9kZXRhaWwtcGFuZWwudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7QUFFYixPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBR2pDLE9BQU8sRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDN0UsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQVE1QyxNQUFNLFVBQVUsV0FBVyxDQUFDLEVBQzFCLElBQUksRUFDSixTQUFTLEVBQ1QsT0FBTyxHQUNVO0lBQ2pCLE1BQU0sT0FBTyxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDL0MsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsTUFBTSxRQUFRLEdBQUcsT0FBTyxHQUFHLFNBQVMsQ0FBQztJQUVyQyxPQUFPLENBQ0wsaUJBQU8sU0FBUyxFQUFDLGlFQUFpRSxhQUNoRixlQUFLLFNBQVMsRUFBQyx1RUFBdUUsYUFDcEYsZUFBTSxTQUFTLEVBQUMsNkNBQTZDLFlBQzFELElBQUksQ0FBQyxJQUFJLEdBQ0wsRUFDUCxLQUFDLFVBQVUsa0JBQVksb0JBQW9CLEVBQUMsT0FBTyxFQUFFLE9BQU8sWUFDMUQsS0FBQyxDQUFDLElBQUMsU0FBUyxFQUFDLFNBQVMsR0FBRyxHQUNkLElBQ1QsRUFDTixjQUFLLFNBQVMsRUFBQywrQkFBK0IsWUFDNUMsY0FBSSxTQUFTLEVBQUMscURBQXFELGFBQ2pFLGFBQUksU0FBUyxFQUFDLGVBQWUseUJBQWMsRUFDM0MsYUFBSSxTQUFTLEVBQUMsMEJBQTBCLFlBQUUsSUFBSSxDQUFDLFFBQVEsR0FBTSxFQUM3RCxhQUFJLFNBQVMsRUFBQyxlQUFlLHlCQUFjLEVBQzNDLGFBQUksU0FBUyxFQUFDLHVDQUF1QyxZQUNsRCxjQUFjLENBQUMsVUFBVSxDQUFDLEdBQ3hCLEVBQ0wsYUFBSSxTQUFTLEVBQUMsZUFBZSx1QkFBWSxFQUN6QyxjQUFJLFNBQVMsRUFBQyx1Q0FBdUMsa0JBQ2pELGNBQWMsQ0FBQyxRQUFRLENBQUMsSUFDdkIsRUFDTCxhQUFJLFNBQVMsRUFBQyxlQUFlLHVCQUFZLEVBQ3pDLGFBQUksU0FBUyxFQUFDLDBCQUEwQixZQUNyQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUNyQyxJQUNGLEdBQ0QsSUFDQSxDQUNULENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBjbGllbnQnO1xuXG5pbXBvcnQgeyBYIH0gZnJvbSAnbHVjaWRlLXJlYWN0JztcbmltcG9ydCB0eXBlIHsgUmVhY3ROb2RlIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IHR5cGUgeyBTcGFuIH0gZnJvbSAnLi4vdHJhY2Utdmlld2VyL3R5cGVzJztcbmltcG9ydCB7IGZvcm1hdER1cmF0aW9uLCBnZXRIaWdoUmVzSW5NcyB9IGZyb20gJy4uL3RyYWNlLXZpZXdlci91dGlsL3RpbWluZyc7XG5pbXBvcnQgeyBJY29uQnV0dG9uIH0gZnJvbSAnLi4vdWkvaWNvbi1idXR0b24nO1xuaW1wb3J0IHsgZ2V0U3BhbkR1cmF0aW9uTXMgfSBmcm9tICcuL3V0aWxzJztcblxuaW50ZXJmYWNlIERldGFpbFBhbmVsUHJvcHMge1xuICBzcGFuOiBTcGFuO1xuICByb290U3RhcnQ6IG51bWJlcjtcbiAgb25DbG9zZTogKCkgPT4gdm9pZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIERldGFpbFBhbmVsKHtcbiAgc3BhbixcbiAgcm9vdFN0YXJ0LFxuICBvbkNsb3NlLFxufTogRGV0YWlsUGFuZWxQcm9wcyk6IFJlYWN0Tm9kZSB7XG4gIGNvbnN0IHN0YXJ0TXMgPSBnZXRIaWdoUmVzSW5NcyhzcGFuLnN0YXJ0VGltZSk7XG4gIGNvbnN0IGR1cmF0aW9uTXMgPSBnZXRTcGFuRHVyYXRpb25NcyhzcGFuKTtcbiAgY29uc3Qgb2Zmc2V0TXMgPSBzdGFydE1zIC0gcm9vdFN0YXJ0O1xuXG4gIHJldHVybiAoXG4gICAgPGFzaWRlIGNsYXNzTmFtZT1cImdyaWQgaC1mdWxsIG1heC1oLWZ1bGwgZ3JpZC1yb3dzLVsyLjVyZW1fMWZyXSBiZy1iYWNrZ3JvdW5kLTIwMFwiPlxuICAgICAgPGRpdiBjbGFzc05hbWU9XCJmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gcHgtMyBib3JkZXItYiBib3JkZXItZ3JheS1hbHBoYS00MDBcIj5cbiAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwidGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LWdyYXktMTAwMCB0cnVuY2F0ZVwiPlxuICAgICAgICAgIHtzcGFuLm5hbWV9XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPEljb25CdXR0b24gYXJpYS1sYWJlbD1cIkNsb3NlIHNwYW4gZGV0YWlsc1wiIG9uQ2xpY2s9e29uQ2xvc2V9PlxuICAgICAgICAgIDxYIGNsYXNzTmFtZT1cInctNCBoLTRcIiAvPlxuICAgICAgICA8L0ljb25CdXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPVwib3ZlcmZsb3cteS1hdXRvIHAtMyBzcGFjZS15LTNcIj5cbiAgICAgICAgPGRsIGNsYXNzTmFtZT1cImdyaWQgZ3JpZC1jb2xzLVthdXRvXzFmcl0gZ2FwLXgtMyBnYXAteS0xLjUgdGV4dC1zbVwiPlxuICAgICAgICAgIDxkdCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktOTAwXCI+UmVzb3VyY2U8L2R0PlxuICAgICAgICAgIDxkZCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktMTAwMCBmb250LW1vbm9cIj57c3Bhbi5yZXNvdXJjZX08L2RkPlxuICAgICAgICAgIDxkdCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktOTAwXCI+RHVyYXRpb248L2R0PlxuICAgICAgICAgIDxkZCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktMTAwMCB0YWJ1bGFyLW51bXMgZm9udC1tb25vXCI+XG4gICAgICAgICAgICB7Zm9ybWF0RHVyYXRpb24oZHVyYXRpb25Ncyl9XG4gICAgICAgICAgPC9kZD5cbiAgICAgICAgICA8ZHQgY2xhc3NOYW1lPVwidGV4dC1ncmF5LTkwMFwiPk9mZnNldDwvZHQ+XG4gICAgICAgICAgPGRkIGNsYXNzTmFtZT1cInRleHQtZ3JheS0xMDAwIHRhYnVsYXItbnVtcyBmb250LW1vbm9cIj5cbiAgICAgICAgICAgICt7Zm9ybWF0RHVyYXRpb24ob2Zmc2V0TXMpfVxuICAgICAgICAgIDwvZGQ+XG4gICAgICAgICAgPGR0IGNsYXNzTmFtZT1cInRleHQtZ3JheS05MDBcIj5TdGF0dXM8L2R0PlxuICAgICAgICAgIDxkZCBjbGFzc05hbWU9XCJ0ZXh0LWdyYXktMTAwMCBmb250LW1vbm9cIj5cbiAgICAgICAgICAgIHtzcGFuLnN0YXR1cy5jb2RlID09PSAyID8gJ0Vycm9yJyA6ICdPSyd9XG4gICAgICAgICAgPC9kZD5cbiAgICAgICAgPC9kbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvYXNpZGU+XG4gICk7XG59XG4iXX0=
@@ -1 +0,0 @@
1
- //# sourceMappingURL=constants.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/components/new-trace-viewer/util/constants.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- "use strict";
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvbmV3LXRyYWNlLXZpZXdlci91dGlsL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiIl19
@@ -1,55 +0,0 @@
1
- 'use client';
2
-
3
- import { X } from 'lucide-react';
4
- import type { ReactNode } from 'react';
5
- import type { Span } from '../trace-viewer/types';
6
- import { formatDuration, getHighResInMs } from '../trace-viewer/util/timing';
7
- import { IconButton } from '../ui/icon-button';
8
- import { getSpanDurationMs } from './utils';
9
-
10
- interface DetailPanelProps {
11
- span: Span;
12
- rootStart: number;
13
- onClose: () => void;
14
- }
15
-
16
- export function DetailPanel({
17
- span,
18
- rootStart,
19
- onClose,
20
- }: DetailPanelProps): ReactNode {
21
- const startMs = getHighResInMs(span.startTime);
22
- const durationMs = getSpanDurationMs(span);
23
- const offsetMs = startMs - rootStart;
24
-
25
- return (
26
- <aside className="grid h-full max-h-full grid-rows-[2.5rem_1fr] bg-background-200">
27
- <div className="flex items-center justify-between px-3 border-b border-gray-alpha-400">
28
- <span className="text-sm font-medium text-gray-1000 truncate">
29
- {span.name}
30
- </span>
31
- <IconButton aria-label="Close span details" onClick={onClose}>
32
- <X className="w-4 h-4" />
33
- </IconButton>
34
- </div>
35
- <div className="overflow-y-auto p-3 space-y-3">
36
- <dl className="grid grid-cols-[auto_1fr] gap-x-3 gap-y-1.5 text-sm">
37
- <dt className="text-gray-900">Resource</dt>
38
- <dd className="text-gray-1000 font-mono">{span.resource}</dd>
39
- <dt className="text-gray-900">Duration</dt>
40
- <dd className="text-gray-1000 tabular-nums font-mono">
41
- {formatDuration(durationMs)}
42
- </dd>
43
- <dt className="text-gray-900">Offset</dt>
44
- <dd className="text-gray-1000 tabular-nums font-mono">
45
- +{formatDuration(offsetMs)}
46
- </dd>
47
- <dt className="text-gray-900">Status</dt>
48
- <dd className="text-gray-1000 font-mono">
49
- {span.status.code === 2 ? 'Error' : 'OK'}
50
- </dd>
51
- </dl>
52
- </div>
53
- </aside>
54
- );
55
- }
File without changes