@workflow/web 5.0.0-beta.17 → 5.0.0-beta.19

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 (27) hide show
  1. package/build/client/assets/{highlighted-body-B3W2YXNL-QKf7Yrcl.js → highlighted-body-B3W2YXNL-BDAdDO0w.js} +1 -1
  2. package/build/client/assets/{home-C2tAadK2.js → home-CJauHJtz.js} +2 -2
  3. package/build/client/assets/index-C7C6cDW5.js +200 -0
  4. package/build/client/assets/{manifest-96e6bcc7.js → manifest-41c15b7c.js} +1 -1
  5. package/build/client/assets/{mermaid-3ZIDBTTL-DQJ4rkIZ.js → mermaid-3ZIDBTTL-CO5WTIpO.js} +554 -293
  6. package/build/client/assets/mermaid-3ZIDBTTL-DYmT7Gxj.css +1 -0
  7. package/build/client/assets/root-1hd8ZXAx.css +1 -0
  8. package/build/client/assets/{root-QCHdCGTF.js → root-YgrrwLRm.js} +1 -1
  9. package/build/client/assets/{run-detail-D4mcR51B.js → run-detail-QryL_6ec.js} +84 -156
  10. package/build/client/assets/server-build-NFow1VGe.css +1 -0
  11. package/build/client/assets/{workflow-graph-viewer-BEhdopGj.js → workflow-graph-viewer-DE9gHUqH.js} +1 -1
  12. package/build/client/assets/zstd-B5R2yJjB.wasm +0 -0
  13. package/build/client/assets/zstd-browser-decoder-Cf0Zee4U.js +27 -0
  14. package/build/server/assets/{app-BEmI6bFe.js → app-BPycGx4j.js} +1 -1
  15. package/build/server/assets/{highlighted-body-B3W2YXNL-B_a6Jc52.js → highlighted-body-B3W2YXNL-DOFGe_gB.js} +2 -2
  16. package/build/server/assets/index-C7C6cDW5.js +200 -0
  17. package/build/server/assets/{index-Bg5S_1qh.js → index-CjQDTwmY.js} +27 -26
  18. package/build/server/assets/{mermaid-3ZIDBTTL-C7y9g953.js → mermaid-3ZIDBTTL-CC2oHOb_.js} +2 -2
  19. package/build/server/assets/{server-build-B3KD951q.js → server-build-D2BAH5fL.js} +744 -318
  20. package/build/server/assets/{token-B95VJmzW.js → token-BuB8DbpT.js} +2 -2
  21. package/build/server/assets/{token-util-q0eyRDZK.js → token-util-bxOuz2AK.js} +2 -2
  22. package/build/server/assets/zstd-browser-decoder-D_rFps2o.js +64 -0
  23. package/build/server/index.js +1 -1
  24. package/package.json +5 -5
  25. package/build/client/assets/mermaid-3ZIDBTTL-CVTQRy2j.css +0 -1
  26. package/build/client/assets/root-D1iC2mNY.css +0 -1
  27. package/build/client/assets/server-build-6KQbeuD8.css +0 -1
@@ -1,6 +1,6 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports, f as reactDomExports, G as ReactDOM, B as useNavigate, C as useSearchParams, A as Link, w as withComponentProps, H as useParams } from "./index-BXZSIDEp.js";
2
- import { q as Check, O as Copy, j as ChevronRight, o as ChevronDown, C as CircleAlert, Q as parseStepName, B as parseWorkflowName, U as ErrorCard, V as format, Z as Zap, S as Send, R as ResolveHookModal, Y as Circle, p as ChevronUp, X, N as ErrorBoundary, I as unwrapServerActionResult, u as unwrapOrThrow, W as WorkflowWebAPIError, _ as useEscapeKeydown, t as composeEventHandlers, $ as useCallbackRef, a0 as useLayoutEffect2, s as useControllableState, a1 as useId, a2 as createContext2, v as Presence, x as createContextScope, l as hideOthers, m as ReactRemoveScroll, a3 as useFocusGuards, a4 as LAYOUT, a5 as wakeUpRun, r as resumeHook, A as Alert, c as AlertTitle, d as AlertDescription, a as Skeleton$1, a6 as RunActionsButtons, F as StatusBadge, e as CopyableText, b as RelativeTime, T as Tabs, K as TabsList, L as TabsTrigger, M as TabsContent, y as cancelRun, a7 as recreateRun } from "./workflow-graph-viewer-BEhdopGj.js";
3
- import { c as createLucideIcon, N as cn, O as DataInspector, U as DecryptClickContext, W as Button, X as Spinner, Y as Lock, Z as RESERVED_ATTRIBUTE_KEY_PREFIX, _ as useHasContextCardProvider, $ as ContextCardProvider, a0 as ContextCardTrigger, g as useToast, a1 as Skeleton, a2 as Yr, a3 as isEncryptedMarker, a4 as formatDuration, a5 as _r, a6 as RunClickContext, a7 as StreamClickContext, a8 as isExpiredMarker, a9 as isDoStreamStep, aa as extractConversation, ab as hasEncryptedFields, ac as EVENT_DATA_REF_FIELDS, ad as useSidebarDataOptional, ae as clsx, af as useRowWindow, ag as isSpanDimmedBySearch, ah as ROW_HEIGHT_PX, ai as getSpanDurationMs, aj as formatDurationPrecise, ak as TooltipProvider, al as ActiveSpanProvider, am as useActiveSpan, an as useSidebarData, ao as searchSpans, ap as computeRootBounds, aq as computeTimeMarkers, ar as getHighResInMs, as as TIMELINE_PADDING_PX, at as Timeline, au as TimelineHeader, av as IconButton, aw as Tooltip, ax as TooltipTrigger, ay as TooltipContent, az as useReducedMotion, aA as SidebarDataProvider, aB as hydrateResourceIOWithKey, aC as hydrateResourceIO, aD as fetchHook, k as fetchEvents, G as fetchRun, aE as fetchStep, aF as fetchStreams, aG as Slot, F as useComposedRefs, aH as Slottable, d as cn$1, aI as buttonVariants, aJ as fetchEvent, aK as fetchEventsByCorrelationId, aL as isEncryptedData, aM as hydrateData, aN as getWebRevivers, T as Tooltip$1, a as TooltipTrigger$1, b as TooltipContent$1, aO as LIVE_UPDATE_INTERVAL_MS$1, u as useServerConfig, aP as getEncryptionKeyForRun, t as toast, L as LoaderCircle, aQ as StreamViewer } from "./mermaid-3ZIDBTTL-DQJ4rkIZ.js";
2
+ import { q as Check, O as Copy, j as ChevronRight, o as ChevronDown, C as CircleAlert, Q as parseStepName, B as parseWorkflowName, U as ErrorCard, V as format, Z as Zap, S as Send, R as ResolveHookModal, Y as Circle, p as ChevronUp, X, N as ErrorBoundary, I as unwrapServerActionResult, u as unwrapOrThrow, W as WorkflowWebAPIError, _ as useEscapeKeydown, t as composeEventHandlers, $ as useCallbackRef, a0 as useLayoutEffect2, s as useControllableState, a1 as useId, a2 as createContext2, v as Presence, x as createContextScope, l as hideOthers, m as ReactRemoveScroll, a3 as useFocusGuards, a4 as LAYOUT, a5 as wakeUpRun, r as resumeHook, A as Alert, c as AlertTitle, d as AlertDescription, a as Skeleton$1, a6 as RunActionsButtons, F as StatusBadge, e as CopyableText, b as RelativeTime, T as Tabs, K as TabsList, L as TabsTrigger, M as TabsContent, y as cancelRun, a7 as recreateRun } from "./workflow-graph-viewer-DE9gHUqH.js";
3
+ import { c as createLucideIcon, O as cn, U as DataInspector, W as DecryptClickContext, X as Button, Y as Spinner, Z as Lock, $ as RESERVED_ATTRIBUTE_KEY_PREFIX, a0 as ContextCardProvider, h as useToast, a1 as Skeleton, a2 as Yr, a3 as isEncryptedMarker, a4 as TimestampTooltip, a5 as formatDuration, a6 as _r, a7 as RunClickContext, a8 as StreamClickContext, a9 as isExpiredMarker, aa as isDoStreamStep, ab as extractConversation, ac as hasEncryptedFields, ad as EVENT_DATA_REF_FIELDS, ae as useSidebarDataOptional, af as clsx, ag as useRowWindow, ah as isSpanDimmedBySearch, ai as ROW_HEIGHT_PX, aj as getSpanDurationMs, ak as formatDurationPrecise, al as TooltipProvider, am as ActiveSpanProvider, an as useActiveSpan, ao as useSidebarData, ap as useReducedMotion, aq as searchSpans, ar as computeRootBounds, as as computeTimeMarkers, at as getHighResInMs, au as scrollRowIntoView, av as TIMELINE_PADDING_PX, aw as Timeline, ax as TimelineHeader, ay as IconButton, az as Tooltip, aA as TooltipTrigger, aB as TooltipContent, aC as SidebarDataProvider, aD as hydrateResourceIOWithKey, aE as hydrateResourceIO, aF as fetchHook, l as fetchEvents, H as fetchRun, aG as fetchStep, aH as fetchStreams, aI as Slot, G as useComposedRefs, aJ as Slottable, e as cn$1, aK as buttonVariants, aL as fetchEvent, aM as fetchEventsByCorrelationId, aN as isEncryptedData, aO as hydrateData, aP as getWebRevivers, T as Tooltip$1, a as TooltipTrigger$1, b as TooltipContent$1, aQ as LIVE_UPDATE_INTERVAL_MS$1, u as useServerConfig, aR as getEncryptionKeyForRun, t as toast, L as LoaderCircle, aS as StreamViewer } from "./mermaid-3ZIDBTTL-CO5WTIpO.js";
4
4
  import { decrypt, importKey } from "./encryption-g14N5vQl.js";
5
5
  import "./index-B6-SzLmT.js";
6
6
  /**
@@ -182,9 +182,7 @@ function ReservedBadge() {
182
182
  }
183
183
  function AttributeRow({ attributeKey, value, removed = false }) {
184
184
  const reserved = isReservedAttributeKey(attributeKey);
185
- return jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3 py-1.5", children: [jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-label-12 font-mono", style: {
186
- color: reserved ? "var(--ds-gray-700)" : "var(--ds-gray-900)"
187
- }, children: [jsxRuntimeExports.jsx("span", { className: "truncate", children: attributeKey }), reserved && jsxRuntimeExports.jsx(ReservedBadge, {})] }), removed ? jsxRuntimeExports.jsx("span", { className: "shrink-0 text-label-12 italic", style: { color: "var(--ds-gray-700)" }, children: "removed" }) : jsxRuntimeExports.jsx("span", { className: "max-w-[60%] truncate text-right text-label-12 font-mono text-gray-1000", title: value, children: value })] });
185
+ return jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3 py-0.5", children: [jsxRuntimeExports.jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-label-13 text-gray-900", style: reserved ? { color: "var(--ds-gray-700)" } : void 0, children: [jsxRuntimeExports.jsx("span", { className: "truncate", children: attributeKey }), reserved && jsxRuntimeExports.jsx(ReservedBadge, {})] }), removed ? jsxRuntimeExports.jsx("span", { className: "shrink-0 text-copy-13 italic text-gray-700", children: "removed" }) : jsxRuntimeExports.jsx("span", { className: "max-w-[60%] truncate text-copy-13 text-gray-1000", title: value, children: value })] });
188
186
  }
189
187
  function sortAttributeKeys(keys) {
190
188
  return [...keys].sort((a, b) => {
@@ -199,7 +197,7 @@ function RunAttributesCard({ attributes }) {
199
197
  const keys = sortAttributeKeys(Object.keys(attributes));
200
198
  if (keys.length === 0)
201
199
  return null;
202
- return jsxRuntimeExports.jsx(DetailCard, { summary: `Attributes (${keys.length})`, defaultOpen: true, contentClassName: "mb-0", children: jsxRuntimeExports.jsx("div", { className: "flex flex-col divide-y divide-gray-alpha-400", children: keys.map((key) => jsxRuntimeExports.jsx(AttributeRow, { attributeKey: key, value: attributes[key] }, key)) }) });
200
+ return jsxRuntimeExports.jsx(DetailCard, { summary: "Attributes", defaultOpen: true, contentClassName: "mb-4", children: jsxRuntimeExports.jsx("div", { className: "flex flex-col", children: keys.map((key) => jsxRuntimeExports.jsx(AttributeRow, { attributeKey: key, value: attributes[key] }, key)) }) });
203
201
  }
204
202
  function isAttrSetEventData(data) {
205
203
  if (data === null || typeof data !== "object")
@@ -222,7 +220,7 @@ function AttrSetEventBlock({ data }) {
222
220
  return jsxRuntimeExports.jsx(CopyableDataBlock, { data });
223
221
  }
224
222
  const writerLabel = describeWriter(data.writer);
225
- return jsxRuntimeExports.jsxs("div", { className: "flex flex-col px-3 py-1", children: [jsxRuntimeExports.jsx("div", { className: "flex flex-col divide-y divide-gray-alpha-400", children: data.changes.map((change, index) => jsxRuntimeExports.jsx(AttributeRow, { attributeKey: change.key, removed: change.value === null, value: change.value ?? void 0 }, `${change.key}:${index}`)) }), writerLabel && jsxRuntimeExports.jsx("div", { className: "border-t py-1.5 text-label-12", style: {
223
+ return jsxRuntimeExports.jsxs("div", { className: "flex flex-col px-3 py-1", children: [jsxRuntimeExports.jsx("div", { className: "flex flex-col", children: data.changes.map((change, index) => jsxRuntimeExports.jsx(AttributeRow, { attributeKey: change.key, removed: change.value === null, value: change.value ?? void 0 }, `${change.key}:${index}`)) }), writerLabel && jsxRuntimeExports.jsx("div", { className: "border-t py-1.5 text-label-12", style: {
226
224
  borderColor: "var(--ds-gray-alpha-400)",
227
225
  color: "var(--ds-gray-700)"
228
226
  }, children: writerLabel })] });
@@ -308,114 +306,6 @@ function MenuDropdown({ options, value, onChange }) {
308
306
  setOpen(false);
309
307
  }, children: option.label }, option.value)) })] });
310
308
  }
311
- const TIME_UNITS = [
312
- { unit: "year", ms: 31536e6 },
313
- { unit: "month", ms: 2628e6 },
314
- { unit: "day", ms: 864e5 },
315
- { unit: "hour", ms: 36e5 },
316
- { unit: "minute", ms: 6e4 },
317
- { unit: "second", ms: 1e3 }
318
- ];
319
- function formatTimeDifference(diff) {
320
- let remaining = Math.abs(diff);
321
- const result = [];
322
- for (const { unit, ms } of TIME_UNITS) {
323
- const value = Math.floor(remaining / ms);
324
- if (value > 0 || result.length > 0) {
325
- result.push(`${value} ${unit}${value !== 1 ? "s" : ""}`);
326
- remaining %= ms;
327
- }
328
- if (result.length === 3)
329
- break;
330
- }
331
- return result.join(", ");
332
- }
333
- function useTimeAgo(date) {
334
- const [timeAgo, setTimeAgo] = reactExports.useState("");
335
- reactExports.useEffect(() => {
336
- const updateTimeAgo = () => {
337
- const diff = Date.now() - date;
338
- const formattedDiff = formatTimeDifference(diff);
339
- setTimeAgo(formattedDiff ? `${formattedDiff} ago` : "Just now");
340
- };
341
- updateTimeAgo();
342
- const timer = setInterval(updateTimeAgo, 1e3);
343
- return () => clearInterval(timer);
344
- }, [date]);
345
- return timeAgo;
346
- }
347
- function useShortTimeAgo(date) {
348
- const [shortTimeAgo, setShortTimeAgo] = reactExports.useState("");
349
- reactExports.useEffect(() => {
350
- if (!date) {
351
- setShortTimeAgo("");
352
- return;
353
- }
354
- const updateShortTimeAgo = () => {
355
- const diff = Date.now() - date;
356
- const days = Math.floor(diff / (1e3 * 60 * 60 * 24));
357
- const hours = Math.floor(diff / (1e3 * 60 * 60));
358
- const minutes = Math.floor(diff / (1e3 * 60));
359
- if (days > 0) {
360
- setShortTimeAgo(`${days} day${days > 1 ? "s" : ""} ago`);
361
- } else if (hours > 0) {
362
- setShortTimeAgo(`${hours} hour${hours > 1 ? "s" : ""} ago`);
363
- } else if (minutes > 0) {
364
- setShortTimeAgo(`${minutes} minute${minutes > 1 ? "s" : ""} ago`);
365
- } else {
366
- setShortTimeAgo("Just now");
367
- }
368
- };
369
- updateShortTimeAgo();
370
- const timer = setInterval(updateShortTimeAgo, 6e4);
371
- return () => clearInterval(timer);
372
- }, [date]);
373
- return shortTimeAgo;
374
- }
375
- function ZoneDateTimeRow({ date, zone }) {
376
- var _a;
377
- const dateObj = new Date(date);
378
- const formattedZone = ((_a = new Intl.DateTimeFormat("en-US", {
379
- timeZone: zone,
380
- timeZoneName: "short"
381
- }).formatToParts(dateObj).find((part) => part.type === "timeZoneName")) == null ? void 0 : _a.value) || zone;
382
- const formattedDate = dateObj.toLocaleString("en-US", {
383
- timeZone: zone,
384
- year: "numeric",
385
- month: "long",
386
- day: "numeric"
387
- });
388
- const formattedTime = dateObj.toLocaleTimeString("en-US", {
389
- timeZone: zone,
390
- hour: "2-digit",
391
- minute: "2-digit",
392
- second: "2-digit"
393
- });
394
- return jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-4 px-1.5 bg-gray-200 rounded-xs", children: jsxRuntimeExports.jsx("span", { className: "text-[12px] font-mono text-gray-900", children: formattedZone }) }), jsxRuntimeExports.jsx("span", { className: "text-[13px] text-gray-1000", children: formattedDate })] }), jsxRuntimeExports.jsx("span", { className: "tabular-nums text-[12px] font-mono text-gray-900", children: formattedTime })] });
395
- }
396
- function RelativeTimeContextCardContent({ date }) {
397
- const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
398
- const timeAgo = useTimeAgo(date);
399
- return jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3 min-w-[300px]", children: [jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-3", children: jsxRuntimeExports.jsx("span", { className: "tabular-nums text-[13px] text-gray-900", children: timeAgo }) }), jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [jsxRuntimeExports.jsx(ZoneDateTimeRow, { date, zone: "UTC" }), jsxRuntimeExports.jsx(ZoneDateTimeRow, { date, zone: localTimezone })] })] });
400
- }
401
- function DefaultTimeText({ date }) {
402
- const shortTimeAgo = useShortTimeAgo(date);
403
- return jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-900", children: shortTimeAgo });
404
- }
405
- function RelativeTimeCard({ date, children: _children, ...props }) {
406
- const children = _children === void 0 ? jsxRuntimeExports.jsx(DefaultTimeText, { date }) : _children;
407
- if (!date)
408
- return children;
409
- return jsxRuntimeExports.jsx(ContextCardTrigger, { content: jsxRuntimeExports.jsx(RelativeTimeContextCardContent, { date }), ...props, children });
410
- }
411
- function TimestampTooltip({ date, children, side = "top" }) {
412
- const hasProvider = useHasContextCardProvider();
413
- const ts = date == null ? null : typeof date === "number" ? date : new Date(date).getTime();
414
- if (ts == null || Number.isNaN(ts))
415
- return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children });
416
- const card = jsxRuntimeExports.jsx(RelativeTimeCard, { date: ts, side, asChild: true, children });
417
- return hasProvider ? card : jsxRuntimeExports.jsx(ContextCardProvider, { children: card });
418
- }
419
309
  const ERROR_EVENT_TYPES$1 = /* @__PURE__ */ new Set([
420
310
  "step_failed",
421
311
  "step_retrying",
@@ -2237,7 +2127,8 @@ const copyableBasicAttributes = /* @__PURE__ */ new Set([
2237
2127
  "stepId",
2238
2128
  "hookId",
2239
2129
  "eventId",
2240
- "deploymentId"
2130
+ "deploymentId",
2131
+ "moduleSpecifier"
2241
2132
  ]);
2242
2133
  const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }) => {
2243
2134
  const decryptCtx = reactExports.useContext(DecryptClickContext);
@@ -2266,7 +2157,6 @@ const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }
2266
2157
  return jsxRuntimeExports.jsxs("div", { className: "relative", children: [typeof isLoading === "boolean" && isLoading && jsxRuntimeExports.jsx("div", { className: "absolute top-9 right-4", children: jsxRuntimeExports.jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2", style: { borderColor: "var(--ds-gray-900)" } }) }), jsxRuntimeExports.jsxs("div", { className: "my-2 flex flex-col gap-0", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-1000 font-medium first-letter:uppercase", children: attribute }), jsxRuntimeExports.jsx("span", { className: "text-xs", style: { color: "var(--ds-gray-1000)" }, children: displayValue })] }, attribute)] });
2267
2158
  };
2268
2159
  const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, onStreamClick, onRunClick, onDecrypt, isDecrypting = false, resource }) => {
2269
- const toast2 = useToast();
2270
2160
  const displayData = reactExports.useMemo(() => {
2271
2161
  const result = { ...data };
2272
2162
  const execCtx = data.executionContext;
@@ -2328,13 +2218,6 @@ const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, on
2328
2218
  const displayContext = reactExports.useMemo(() => ({
2329
2219
  stepName: displayData.stepName
2330
2220
  }), [displayData.stepName]);
2331
- const handleCopyModuleSpecifier = reactExports.useCallback((value) => {
2332
- navigator.clipboard.writeText(value).then(() => {
2333
- toast2.success("moduleSpecifier copied");
2334
- }).catch(() => {
2335
- toast2.error("Failed to copy moduleSpecifier");
2336
- });
2337
- }, []);
2338
2221
  const outerDecryptCtx = reactExports.useContext(DecryptClickContext);
2339
2222
  const decryptValue = onDecrypt ? {
2340
2223
  onDecrypt,
@@ -2344,17 +2227,8 @@ const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, on
2344
2227
  return jsxRuntimeExports.jsx(ContextCardProvider, { children: jsxRuntimeExports.jsx(RunClickContext.Provider, { value: onRunClick, children: jsxRuntimeExports.jsx(StreamClickContext.Provider, { value: onStreamClick, children: jsxRuntimeExports.jsxs(DecryptClickContext.Provider, { value: decryptValue, children: [visibleBasicAttributes.length > 0 && jsxRuntimeExports.jsxs("div", { className: "flex flex-col overflow-hidden divide-y divide-gray-alpha-400 mb-3", children: [orderedBasicAttributes.map((attribute) => {
2345
2228
  var _a;
2346
2229
  const displayValue = (_a = attributeToDisplayFn[attribute]) == null ? void 0 : _a.call(attributeToDisplayFn, displayData[attribute]);
2347
- const isModuleSpecifier = attribute === "moduleSpecifier";
2348
2230
  const isCopyableBasicAttribute = copyableBasicAttributes.has(attribute) && typeof displayValue === "string";
2349
- const moduleSpecifierValue = typeof displayValue === "string" ? displayValue : String(displayValue ?? displayData.moduleSpecifier ?? "");
2350
- return jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between py-2", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-900", children: getAttributeDisplayName(attribute) }), isModuleSpecifier ? jsxRuntimeExports.jsx("button", { type: "button", className: "min-w-0 max-w-[70%] truncate text-right text-label-13 font-mono", style: {
2351
- color: "var(--ds-gray-1000)",
2352
- background: "transparent",
2353
- border: "none",
2354
- padding: 0
2355
- }, title: moduleSpecifierValue, onClick: () => handleCopyModuleSpecifier(moduleSpecifierValue), children: moduleSpecifierValue }) : isCopyableBasicAttribute ? jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 max-w-[70%] items-center justify-end gap-1 text-right text-[13px] font-mono", style: {
2356
- color: "var(--ds-gray-1000)"
2357
- }, title: displayValue, children: [jsxRuntimeExports.jsx(MiddleTruncate, { value: displayValue, className: "flex-1" }), jsxRuntimeExports.jsx(CopyButton, { copyText: displayValue, ariaLabel: `Copy ${getAttributeDisplayName(attribute)}`, className: "shrink-0 -mr-1" })] }) : jsxRuntimeExports.jsx("span", { className: "text-right text-label-13 font-mono", children: displayValue })] }, attribute);
2231
+ return jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between py-2", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-900", children: getAttributeDisplayName(attribute) }), isCopyableBasicAttribute ? jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 max-w-[70%] items-center justify-end gap-1 text-[13px] font-mono text-gray-1000", title: displayValue, children: [jsxRuntimeExports.jsx(MiddleTruncate, { value: displayValue, className: "text-right", style: { gridTemplateColumns: "minmax(0, 1fr)" } }), jsxRuntimeExports.jsx(CopyButton, { copyText: displayValue, ariaLabel: `Copy ${getAttributeDisplayName(attribute)}`, className: "shrink-0 -mr-1" })] }) : jsxRuntimeExports.jsx("span", { className: "text-right text-label-13 font-mono", children: displayValue })] }, attribute);
2358
2232
  }), isLoading && resource === "sleep" && !displayData.resumeAt && jsxRuntimeExports.jsx("div", { className: "py-1", children: jsxRuntimeExports.jsxs("div", { className: "flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1", children: [jsxRuntimeExports.jsx("span", { className: "text-[14px] first-letter:uppercase", style: { color: "var(--ds-gray-700)" }, children: "resumeAt" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-[55%]" })] }) })] }), error ? jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load resource details", details: error.message, className: "my-4" }) : hasExpired ? jsxRuntimeExports.jsx(ExpiredDataMessage, {}) : resolvedAttributes.length > 0 ? jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: resolvedAttributes.map((attribute) => jsxRuntimeExports.jsx(AttributeBlock, { isLoading, attribute, value: displayData[attribute], context: displayContext }, attribute)) }) : null] }) }) }) });
2359
2233
  };
2360
2234
  const ERROR_EVENT_TYPES = /* @__PURE__ */ new Set(["step_failed", "step_retrying"]);
@@ -2902,6 +2776,7 @@ function SplitPane({ children, className, defaultStartWidth = DEFAULT_START_PX,
2902
2776
  return jsxRuntimeExports.jsxs("div", { ref: setContainerRef, className: cn("grid h-full min-h-0 content-start overflow-x-hidden overflow-y-auto", isDragging && "select-none", className), style: { gridTemplateColumns: colTemplate, height: "100%" }, children: [start, gutter, end] });
2903
2777
  }
2904
2778
  const MIN_VIEWPORT_MS = 1e-3;
2779
+ const ZOOM_DEBOUNCE_MS = 150;
2905
2780
  function useAnimatedViewport(initial) {
2906
2781
  const [viewport, setViewportState] = reactExports.useState(initial);
2907
2782
  const animRef = reactExports.useRef(null);
@@ -2978,6 +2853,7 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
2978
2853
  const { activeSpan, activeSpanId, setActiveSpan, clearActiveSpan } = useActiveSpan();
2979
2854
  const sidebar = useSidebarData();
2980
2855
  const selectedSpan = useSelectedSpanInfo();
2856
+ const reducedMotion = useReducedMotion();
2981
2857
  const [searchQuery, setSearchQuery] = reactExports.useState("");
2982
2858
  const deferredSearchQuery = reactExports.useDeferredValue(searchQuery);
2983
2859
  const searchResult = reactExports.useMemo(() => searchSpans(trace.spans, deferredSearchQuery), [trace.spans, deferredSearchQuery]);
@@ -3013,10 +2889,29 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3013
2889
  prevRootRef.current = { start: newStart, end: newEnd };
3014
2890
  }, [root.startTime, root.duration, setViewport]);
3015
2891
  const viewDuration = viewport.end - viewport.start;
2892
+ const viewportRef = reactExports.useRef(viewport);
2893
+ viewportRef.current = viewport;
3016
2894
  const timeMarkers = reactExports.useMemo(() => computeTimeMarkers(viewDuration, viewport.start - root.startTime), [viewDuration, viewport.start, root.startTime]);
3017
2895
  const resetZoom = reactExports.useCallback(() => {
3018
2896
  animateTo({ start: root.startTime, end: root.startTime + root.duration });
3019
2897
  }, [animateTo, root.startTime, root.duration]);
2898
+ const handleRevealTime = reactExports.useCallback((timeMs) => {
2899
+ const rootS = root.startTime;
2900
+ const rootE = root.startTime + root.duration;
2901
+ const { start, end } = viewportRef.current;
2902
+ const duration = end - start;
2903
+ let newStart = timeMs - duration / 2;
2904
+ let newEnd = timeMs + duration / 2;
2905
+ if (newStart < rootS) {
2906
+ newStart = rootS;
2907
+ newEnd = rootS + duration;
2908
+ }
2909
+ if (newEnd > rootE) {
2910
+ newEnd = rootE;
2911
+ newStart = Math.max(rootS, rootE - duration);
2912
+ }
2913
+ animateTo({ start: newStart, end: newEnd });
2914
+ }, [animateTo, root.startTime, root.duration]);
3020
2915
  const ZOOM_FACTOR = 0.5;
3021
2916
  const zoomBy = reactExports.useCallback((factor) => {
3022
2917
  const rootS = root.startTime;
@@ -3041,12 +2936,7 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3041
2936
  }, [setViewport, root.startTime, root.duration]);
3042
2937
  const zoomIn = reactExports.useCallback(() => zoomBy(ZOOM_FACTOR), [zoomBy]);
3043
2938
  const zoomOut = reactExports.useCallback(() => zoomBy(1 / ZOOM_FACTOR), [zoomBy]);
3044
- const handleSelectSpan = reactExports.useCallback((spanId) => {
3045
- if (spanId === activeSpanId) {
3046
- clearActiveSpan();
3047
- return;
3048
- }
3049
- setActiveSpan(spanId);
2939
+ const focusViewportOnSpan = reactExports.useCallback((spanId) => {
3050
2940
  const span = trace.spans.find((s) => s.spanId === spanId);
3051
2941
  if (!span)
3052
2942
  return;
@@ -3079,15 +2969,53 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3079
2969
  newStart = Math.max(rootS, rootE - duration);
3080
2970
  }
3081
2971
  animateTo({ start: newStart, end: newEnd });
2972
+ }, [animateTo, trace.spans, root.startTime, root.duration]);
2973
+ const scrollSpanIntoView = reactExports.useCallback((spanId) => {
2974
+ var _a;
2975
+ const index = trace.spans.findIndex((s) => s.spanId === spanId);
2976
+ if (index === -1)
2977
+ return;
2978
+ const list = ((_a = scrollContainerRef.current) == null ? void 0 : _a.querySelector("#event-list")) ?? null;
2979
+ scrollRowIntoView(list, index, ROW_HEIGHT_PX, {
2980
+ behavior: reducedMotion ? "auto" : "smooth"
2981
+ });
2982
+ }, [trace.spans, reducedMotion]);
2983
+ const zoomTimerRef = reactExports.useRef(null);
2984
+ const cancelPendingZoom = reactExports.useCallback(() => {
2985
+ if (zoomTimerRef.current !== null) {
2986
+ clearTimeout(zoomTimerRef.current);
2987
+ zoomTimerRef.current = null;
2988
+ }
2989
+ }, []);
2990
+ reactExports.useEffect(() => cancelPendingZoom, [cancelPendingZoom]);
2991
+ const handleClearActiveSpan = reactExports.useCallback(() => {
2992
+ cancelPendingZoom();
2993
+ clearActiveSpan();
2994
+ }, [cancelPendingZoom, clearActiveSpan]);
2995
+ const handleSelectSpan = reactExports.useCallback((spanId) => {
2996
+ cancelPendingZoom();
2997
+ if (spanId === activeSpanId) {
2998
+ clearActiveSpan();
2999
+ return;
3000
+ }
3001
+ setActiveSpan(spanId);
3002
+ focusViewportOnSpan(spanId);
3082
3003
  }, [
3083
- animateTo,
3084
- setActiveSpan,
3085
- clearActiveSpan,
3004
+ cancelPendingZoom,
3086
3005
  activeSpanId,
3087
- trace.spans,
3088
- root.startTime,
3089
- root.duration
3006
+ clearActiveSpan,
3007
+ setActiveSpan,
3008
+ focusViewportOnSpan
3090
3009
  ]);
3010
+ const navigateToSpan = reactExports.useCallback((spanId) => {
3011
+ setActiveSpan(spanId);
3012
+ scrollSpanIntoView(spanId);
3013
+ cancelPendingZoom();
3014
+ zoomTimerRef.current = setTimeout(() => {
3015
+ zoomTimerRef.current = null;
3016
+ focusViewportOnSpan(spanId);
3017
+ }, ZOOM_DEBOUNCE_MS);
3018
+ }, [setActiveSpan, scrollSpanIntoView, cancelPendingZoom, focusViewportOnSpan]);
3091
3019
  const [altHeld, setAltHeld] = reactExports.useState(false);
3092
3020
  reactExports.useEffect(() => {
3093
3021
  const handleSidebarNavKey = (e) => {
@@ -3098,12 +3026,12 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3098
3026
  const targetId = e.key === "k" ? prevSpanIdRef.current : nextSpanIdRef.current;
3099
3027
  if (targetId) {
3100
3028
  e.preventDefault();
3101
- handleSelectSpanRef.current(targetId);
3029
+ navigateToSpanRef.current(targetId);
3102
3030
  }
3103
3031
  };
3104
3032
  const onKeyDown = (e) => {
3105
3033
  if (e.key === "Escape") {
3106
- clearActiveSpan();
3034
+ handleClearActiveSpan();
3107
3035
  } else if (e.key === "Alt") {
3108
3036
  e.preventDefault();
3109
3037
  setAltHeld(true);
@@ -3124,7 +3052,7 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3124
3052
  window.removeEventListener("keyup", onKeyUp);
3125
3053
  window.removeEventListener("blur", onBlur);
3126
3054
  };
3127
- }, [clearActiveSpan]);
3055
+ }, [handleClearActiveSpan]);
3128
3056
  const timelineRef = reactExports.useRef(null);
3129
3057
  const [hoverFraction, setHoverFraction] = reactExports.useState(null);
3130
3058
  const hoverInfo = reactExports.useMemo(() => {
@@ -3240,25 +3168,25 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3240
3168
  }, [activeSpanId, trace.spans]);
3241
3169
  const handleSelectPrevSpan = reactExports.useCallback(() => {
3242
3170
  if (prevSpanId)
3243
- handleSelectSpan(prevSpanId);
3244
- }, [prevSpanId, handleSelectSpan]);
3171
+ navigateToSpan(prevSpanId);
3172
+ }, [prevSpanId, navigateToSpan]);
3245
3173
  const handleSelectNextSpan = reactExports.useCallback(() => {
3246
3174
  if (nextSpanId)
3247
- handleSelectSpan(nextSpanId);
3248
- }, [nextSpanId, handleSelectSpan]);
3175
+ navigateToSpan(nextSpanId);
3176
+ }, [nextSpanId, navigateToSpan]);
3249
3177
  const prevSpanIdRef = reactExports.useRef(prevSpanId);
3250
3178
  const nextSpanIdRef = reactExports.useRef(nextSpanId);
3251
- const handleSelectSpanRef = reactExports.useRef(handleSelectSpan);
3179
+ const navigateToSpanRef = reactExports.useRef(navigateToSpan);
3252
3180
  prevSpanIdRef.current = prevSpanId;
3253
3181
  nextSpanIdRef.current = nextSpanId;
3254
- handleSelectSpanRef.current = handleSelectSpan;
3182
+ navigateToSpanRef.current = navigateToSpan;
3255
3183
  return jsxRuntimeExports.jsxs("div", { "data-pane": "pane-root", "data-has-detail": activeSpan ? "" : void 0, 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%)]", children: [jsxRuntimeExports.jsxs("div", { id: "trace-parent", className: "grid grid-rows-[1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [jsxRuntimeExports.jsxs(SplitPane, { scrollContainerRef, startHeader: jsxRuntimeExports.jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center pl-4 pr-2 gap-1.5", children: [jsxRuntimeExports.jsx(Search, { className: "w-3.5 h-3.5 shrink-0 text-gray-800" }), jsxRuntimeExports.jsx("input", { id: "trace-viewer-search", name: "trace-viewer-search", type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: (e) => {
3256
3184
  if (e.key === "Escape" && searchQuery) {
3257
3185
  e.preventDefault();
3258
3186
  e.stopPropagation();
3259
3187
  setSearchQuery("");
3260
3188
  }
3261
- }, placeholder: "Search spans...", "aria-label": "Search spans", className: "flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none" }), searchQuery && jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Clear search", onClick: () => setSearchQuery(""), className: "-mr-2 hidden h-full max-w-full shrink-0 cursor-pointer items-center rounded-r-md border-0 bg-transparent px-2.5 font-inherit text-base text-gray-900 no-underline transition-colors duration-150 ease-in hover:text-gray-1000 focus-visible:-outline-offset-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--ds-focus-color)] min-[961px]:flex", children: jsxRuntimeExports.jsx("kbd", { className: "inline-flex h-5 min-h-5 min-w-5 items-center justify-center rounded border border-gray-alpha-400 bg-background-100 px-1 font-sans text-[13px] font-medium leading-[1.7em] text-gray-900", children: "Esc" }) })] }), endHeader: jsxRuntimeExports.jsx(TimelineHeader, { markers: timeMarkers, hoverInfo }), children: [jsxRuntimeExports.jsxs("div", { className: "block overflow-visible", children: [jsxRuntimeExports.jsx(EventList, { spans: trace.spans, activeSpanId, searchResult, onSelectSpan: handleSelectSpan }), jsxRuntimeExports.jsx("div", { ref: loadMoreSentinelRef, className: "flex justify-center", children: isLoadingMore ? jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center gap-2 py-3 text-sm text-gray-800", children: [jsxRuntimeExports.jsx(Spinner, { size: 14 }), jsxRuntimeExports.jsx("span", { children: "Loading spans…" })] }) : null })] }), jsxRuntimeExports.jsx("div", { ref: timelineRef, className: "block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: jsxRuntimeExports.jsx(Timeline, { spans: trace.spans, viewStart: viewport.start, viewEnd: viewport.end, markers: timeMarkers, selectedId: activeSpanId, searchResult, onSelect: handleSelectSpan, hoverFraction, altHeld }) })] }), jsxRuntimeExports.jsxs("div", { className: "absolute right-3 bottom-3 z-[5] flex items-center border border-gray-alpha-400 rounded-md bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400", children: [jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomOut, "aria-label": "Zoom out", children: jsxRuntimeExports.jsx(ZoomOut, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: resetZoom, "aria-label": "Reset zoom", children: jsxRuntimeExports.jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomIn, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), activeSpan ? jsxRuntimeExports.jsxs("aside", { className: "flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 shrink-0 px-4 pt-3 pb-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 font-medium text-gray-1000 truncate block", children: selectedSpanName }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [jsxRuntimeExports.jsxs(Tooltip, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate up", "aria-keyshortcuts": "K", onClick: handleSelectPrevSpan, disabled: !prevSpanId, children: jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }) }), prevSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { children: ["Navigate up", jsxRuntimeExports.jsx(Kbd, { children: "K" })] }) : null] }), jsxRuntimeExports.jsxs(Tooltip, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate down", "aria-keyshortcuts": "J", onClick: handleSelectNextSpan, disabled: !nextSpanId, children: jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" }) }) }), nextSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { children: ["Navigate down", jsxRuntimeExports.jsx(Kbd, { children: "J" })] }) : null] }), jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "w-px h-4 bg-gray-alpha-400 mx-1" }), jsxRuntimeExports.jsx(IconButton, { "aria-label": "Close span details", "aria-keyshortcuts": "Escape", onClick: clearActiveSpan, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(EntityDetailPanel, { run: sidebar.run, onStreamClick: sidebar.onStreamClick, onRunClick: sidebar.onRunClick, spanDetailData: sidebar.spanDetailData, spanDetailError: sidebar.spanDetailError, spanDetailLoading: sidebar.spanDetailLoading, onSpanSelect: sidebar.onSpanSelect, onWakeUpSleep: sidebar.onWakeUpSleep, onLoadEventData: sidebar.onLoadEventData, onResolveHook: sidebar.onResolveHook, encryptionKey: sidebar.encryptionKey, onDecrypt: sidebar.onDecrypt, isDecrypting: sidebar.isDecrypting, selectedSpan }) }) })] }) : null] });
3189
+ }, placeholder: "Search spans...", "aria-label": "Search spans", className: "flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none" }), searchQuery && jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Clear search", onClick: () => setSearchQuery(""), className: "-mr-2 hidden h-full max-w-full shrink-0 cursor-pointer items-center rounded-r-md border-0 bg-transparent px-2.5 font-inherit text-base text-gray-900 no-underline transition-colors duration-150 ease-in hover:text-gray-1000 focus-visible:-outline-offset-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--ds-focus-color)] min-[961px]:flex", children: jsxRuntimeExports.jsx("kbd", { className: "inline-flex h-5 min-h-5 min-w-5 items-center justify-center rounded border border-gray-alpha-400 bg-background-100 px-1 font-sans text-[13px] font-medium leading-[1.7em] text-gray-900", children: "Esc" }) })] }), endHeader: jsxRuntimeExports.jsx(TimelineHeader, { markers: timeMarkers, hoverInfo }), children: [jsxRuntimeExports.jsxs("div", { className: "block overflow-visible", children: [jsxRuntimeExports.jsx(EventList, { spans: trace.spans, activeSpanId, searchResult, onSelectSpan: handleSelectSpan }), jsxRuntimeExports.jsx("div", { ref: loadMoreSentinelRef, className: "flex justify-center", children: isLoadingMore ? jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center gap-2 py-3 text-sm text-gray-800", children: [jsxRuntimeExports.jsx(Spinner, { size: 14 }), jsxRuntimeExports.jsx("span", { children: "Loading spans…" })] }) : null })] }), jsxRuntimeExports.jsx("div", { ref: timelineRef, className: "block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: jsxRuntimeExports.jsx(Timeline, { spans: trace.spans, viewStart: viewport.start, viewEnd: viewport.end, markers: timeMarkers, selectedId: activeSpanId, searchResult, onSelect: handleSelectSpan, onRevealTime: handleRevealTime, hoverFraction, altHeld }) })] }), jsxRuntimeExports.jsxs("div", { className: "absolute right-3 bottom-3 z-[5] flex items-center border border-gray-alpha-400 rounded-md bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400", children: [jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomOut, "aria-label": "Zoom out", children: jsxRuntimeExports.jsx(ZoomOut, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: resetZoom, "aria-label": "Reset zoom", children: jsxRuntimeExports.jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomIn, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), activeSpan ? jsxRuntimeExports.jsxs("aside", { className: "flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 shrink-0 px-4 pt-3 pb-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 font-medium text-gray-1000 truncate block", children: selectedSpanName }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [jsxRuntimeExports.jsxs(Tooltip, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate up", "aria-keyshortcuts": "K", onClick: handleSelectPrevSpan, disabled: !prevSpanId, children: jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }) }), prevSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { children: ["Navigate up", jsxRuntimeExports.jsx(Kbd, { children: "K" })] }) : null] }), jsxRuntimeExports.jsxs(Tooltip, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate down", "aria-keyshortcuts": "J", onClick: handleSelectNextSpan, disabled: !nextSpanId, children: jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" }) }) }), nextSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { children: ["Navigate down", jsxRuntimeExports.jsx(Kbd, { children: "J" })] }) : null] }), jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "w-px h-4 bg-gray-alpha-400 mx-1" }), jsxRuntimeExports.jsx(IconButton, { "aria-label": "Close span details", "aria-keyshortcuts": "Escape", onClick: handleClearActiveSpan, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary, { children: jsxRuntimeExports.jsx(EntityDetailPanel, { run: sidebar.run, onStreamClick: sidebar.onStreamClick, onRunClick: sidebar.onRunClick, spanDetailData: sidebar.spanDetailData, spanDetailError: sidebar.spanDetailError, spanDetailLoading: sidebar.spanDetailLoading, onSpanSelect: sidebar.onSpanSelect, onWakeUpSleep: sidebar.onWakeUpSleep, onLoadEventData: sidebar.onLoadEventData, onResolveHook: sidebar.onResolveHook, encryptionKey: sidebar.encryptionKey, onDecrypt: sidebar.onDecrypt, isDecrypting: sidebar.isDecrypting, selectedSpan }) }) })] }) : null] });
3262
3190
  }
3263
3191
  const NewTraceViewer = ({ run, events, sidebarData, onLoadMore, hasMore, isLoadingMore, loading = false }) => {
3264
3192
  const trace = reactExports.useMemo(() => {