@mastra/playground-ui 48.0.0 → 48.1.0-alpha.1
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/CHANGELOG.md +51 -0
- package/dist/Composer.css +2 -2
- package/dist/{code-C5KVVzOZ.js → code-Cj09LVys.js} +2 -2
- package/dist/{code-C5KVVzOZ.js.map → code-Cj09LVys.js.map} +1 -1
- package/dist/{code-B3WONxnA.cjs → code-FZwLnf_f.cjs} +2 -2
- package/dist/{code-B3WONxnA.cjs.map → code-FZwLnf_f.cjs.map} +1 -1
- package/dist/code-block-Dn0K3DkE.cjs +88 -0
- package/dist/code-block-Dn0K3DkE.cjs.map +1 -0
- package/dist/code-block-DqKXZajq.js +86 -0
- package/dist/code-block-DqKXZajq.js.map +1 -0
- package/dist/components/Code.cjs.js +1 -1
- package/dist/components/Code.es.js +1 -1
- package/dist/components/CodeBlock.cjs.js +3 -83
- package/dist/components/CodeBlock.cjs.js.map +1 -1
- package/dist/components/CodeBlock.es.js +1 -85
- package/dist/components/CodeBlock.es.js.map +1 -1
- package/dist/components/CodeEditor.cjs.js +2 -2
- package/dist/components/CodeEditor.es.js +2 -2
- package/dist/components/CopyButton.cjs.js +1 -1
- package/dist/components/CopyButton.es.js +1 -1
- package/dist/components/DataCodeSection.cjs.js +1 -1
- package/dist/components/DataCodeSection.es.js +1 -1
- package/dist/components/DataDetailsPanel.cjs.js +1 -1
- package/dist/components/DataDetailsPanel.es.js +1 -1
- package/dist/components/DataPanel.cjs.js +1 -1
- package/dist/components/DataPanel.es.js +1 -1
- package/dist/components/MarkdownRenderer.cjs.js +1 -1
- package/dist/components/MarkdownRenderer.es.js +1 -1
- package/dist/components/SideDialog.cjs.js +1 -1
- package/dist/components/SideDialog.es.js +1 -1
- package/dist/components/Truncate.cjs.js +1 -1
- package/dist/components/Truncate.es.js +1 -1
- package/dist/components/ai/plan.cjs.js +2 -2
- package/dist/components/ai/plan.cjs.js.map +1 -1
- package/dist/components/ai/plan.es.js +2 -2
- package/dist/components/ai/plan.es.js.map +1 -1
- package/dist/components/ai/task-list.cjs.js +44 -18
- package/dist/components/ai/task-list.cjs.js.map +1 -1
- package/dist/components/ai/task-list.es.js +47 -21
- package/dist/components/ai/task-list.es.js.map +1 -1
- package/dist/{copy-button-B1GWIQ-x.js → copy-button-BLGUkVE8.js} +4 -2
- package/dist/copy-button-BLGUkVE8.js.map +1 -0
- package/dist/{copy-button-DwZ3c7D4.cjs → copy-button-BfawWA4t.cjs} +4 -2
- package/dist/copy-button-BfawWA4t.cjs.map +1 -0
- package/dist/{data-code-section-PJM5l3aS.js → data-code-section-DHbytoQ2.js} +2 -2
- package/dist/{data-code-section-PJM5l3aS.js.map → data-code-section-DHbytoQ2.js.map} +1 -1
- package/dist/{data-code-section-BjmFgJpC.cjs → data-code-section-bqvIovEN.cjs} +2 -2
- package/dist/{data-code-section-BjmFgJpC.cjs.map → data-code-section-bqvIovEN.cjs.map} +1 -1
- package/dist/{data-panel-BQqPr6ew.js → data-panel-BX_78wCj.js} +2 -2
- package/dist/{data-panel-BQqPr6ew.js.map → data-panel-BX_78wCj.js.map} +1 -1
- package/dist/{data-panel-C85h9XvH.cjs → data-panel-DT6LgTVX.cjs} +2 -2
- package/dist/{data-panel-C85h9XvH.cjs.map → data-panel-DT6LgTVX.cjs.map} +1 -1
- package/dist/domains/logs/components/log-details-view.cjs.js +1 -1
- package/dist/domains/logs/components/log-details-view.es.js +1 -1
- package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
- package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.cjs.js +1 -1
- package/dist/domains/traces/components/trace-data-panel-view.es.js +1 -1
- package/dist/ee/signals/entity-learning-api.cjs.js +8 -2
- package/dist/ee/signals/entity-learning-api.cjs.js.map +1 -1
- package/dist/ee/signals/entity-learning-api.es.js +8 -3
- package/dist/ee/signals/entity-learning-api.es.js.map +1 -1
- package/dist/ee/signals/hooks/use-noise-examples.cjs.js +5 -3
- package/dist/ee/signals/hooks/use-noise-examples.cjs.js.map +1 -1
- package/dist/ee/signals/hooks/use-noise-examples.es.js +6 -4
- package/dist/ee/signals/hooks/use-noise-examples.es.js.map +1 -1
- package/dist/ee/signals/hooks/use-theme-examples.cjs.js +6 -3
- package/dist/ee/signals/hooks/use-theme-examples.cjs.js.map +1 -1
- package/dist/ee/signals/hooks/use-theme-examples.es.js +7 -4
- package/dist/ee/signals/hooks/use-theme-examples.es.js.map +1 -1
- package/dist/ee/signals/hooks/use-theme-paths.cjs.js +2 -2
- package/dist/ee/signals/hooks/use-theme-paths.cjs.js.map +1 -1
- package/dist/ee/signals/hooks/use-theme-paths.es.js +3 -3
- package/dist/ee/signals/hooks/use-theme-paths.es.js.map +1 -1
- package/dist/ee/signals/lifeline-row.cjs.js +1 -1
- package/dist/ee/signals/lifeline-row.cjs.js.map +1 -1
- package/dist/ee/signals/lifeline-row.es.js +1 -1
- package/dist/ee/signals/lifeline-row.es.js.map +1 -1
- package/dist/ee/signals/noise-detail-panel.cjs.js +18 -5
- package/dist/ee/signals/noise-detail-panel.cjs.js.map +1 -1
- package/dist/ee/signals/noise-detail-panel.es.js +18 -5
- package/dist/ee/signals/noise-detail-panel.es.js.map +1 -1
- package/dist/ee/signals/sankey-signals.cjs.js +50 -34
- package/dist/ee/signals/sankey-signals.cjs.js.map +1 -1
- package/dist/ee/signals/sankey-signals.es.js +52 -36
- package/dist/ee/signals/sankey-signals.es.js.map +1 -1
- package/dist/ee/signals/signal-delta-column.cjs.js +1 -1
- package/dist/ee/signals/signal-delta-column.cjs.js.map +1 -1
- package/dist/ee/signals/signal-delta-column.es.js +1 -1
- package/dist/ee/signals/signal-delta-column.es.js.map +1 -1
- package/dist/ee/signals/theme-detail-panel.cjs.js +11 -4
- package/dist/ee/signals/theme-detail-panel.cjs.js.map +1 -1
- package/dist/ee/signals/theme-detail-panel.es.js +11 -4
- package/dist/ee/signals/theme-detail-panel.es.js.map +1 -1
- package/dist/ee/signals/theme-drilldown-data.cjs.js +41 -13
- package/dist/ee/signals/theme-drilldown-data.cjs.js.map +1 -1
- package/dist/ee/signals/theme-drilldown-data.es.js +40 -14
- package/dist/ee/signals/theme-drilldown-data.es.js.map +1 -1
- package/dist/ee/signals/theme-filter-banner.cjs.js +53 -28
- package/dist/ee/signals/theme-filter-banner.cjs.js.map +1 -1
- package/dist/ee/signals/theme-filter-banner.es.js +53 -28
- package/dist/ee/signals/theme-filter-banner.es.js.map +1 -1
- package/dist/{highlight-C2uRVhiA.cjs → highlight-CEt2vhD8.cjs} +20 -3
- package/dist/highlight-CEt2vhD8.cjs.map +1 -0
- package/dist/{highlight-Dis62bkj.js → highlight-CSJjjoqh.js} +20 -3
- package/dist/highlight-CSJjjoqh.js.map +1 -0
- package/dist/markdown-renderer-D1vSFfp9.cjs +86 -0
- package/dist/markdown-renderer-D1vSFfp9.cjs.map +1 -0
- package/dist/markdown-renderer-DmYYQHxu.js +84 -0
- package/dist/markdown-renderer-DmYYQHxu.js.map +1 -0
- package/dist/markdown-renderer.css +182 -0
- package/dist/src/ds/components/CopyButton/copy-button.d.ts +2 -1
- package/dist/src/ds/components/MarkdownRenderer/markdown-renderer.d.ts +9 -5
- package/dist/src/ds/components/ai/task-list/task-list.d.ts +4 -2
- package/dist/src/ds/components/ai/task-list/task-list.stories.d.ts +2 -0
- package/dist/src/ee/signals/entity-learning-api.d.ts +4 -2
- package/dist/src/ee/signals/hooks/use-noise-examples.d.ts +2 -1
- package/dist/src/ee/signals/hooks/use-theme-examples.d.ts +2 -1
- package/dist/src/ee/signals/hooks/use-theme-paths.d.ts +1 -1
- package/dist/src/ee/signals/noise-detail-panel.d.ts +4 -1
- package/dist/src/ee/signals/theme-detail-panel.d.ts +5 -3
- package/dist/src/ee/signals/theme-drilldown-data.d.ts +17 -4
- package/dist/src/ee/signals/theme-filter-banner.d.ts +5 -3
- package/dist/style.css +5 -98
- package/package.json +7 -7
- package/dist/copy-button-B1GWIQ-x.js.map +0 -1
- package/dist/copy-button-DwZ3c7D4.cjs.map +0 -1
- package/dist/highlight-C2uRVhiA.cjs.map +0 -1
- package/dist/highlight-Dis62bkj.js.map +0 -1
- package/dist/markdown-renderer-DszxuuNM.js +0 -117
- package/dist/markdown-renderer-DszxuuNM.js.map +0 -1
- package/dist/markdown-renderer-g8xNLOc0.cjs +0 -119
- package/dist/markdown-renderer-g8xNLOc0.cjs.map +0 -1
|
@@ -3,7 +3,7 @@ import { useQueryClient, useMutation } from '@tanstack/react-query';
|
|
|
3
3
|
import { Waypoints, ArrowLeftRight, ChartNoAxesGantt } from 'lucide-react';
|
|
4
4
|
import { useState, useMemo } from 'react';
|
|
5
5
|
import { SignalsOverviewPage } from './components/signals-overview-page.es.js';
|
|
6
|
-
import { fetchThemeSnapshots, fetchThemeFlow, fetchThemePaths } from './entity-learning-api.es.js';
|
|
6
|
+
import { fetchThemeSnapshots, fetchThemeFlow, fetchThemePaths, serializeThemeFilters } from './entity-learning-api.es.js';
|
|
7
7
|
import { FlowCard } from './flow-card.es.js';
|
|
8
8
|
import { useEntityLearningProgress } from './hooks/use-entity-learning-progress.es.js';
|
|
9
9
|
import { useSnapshotPlayback } from './hooks/use-snapshot-playback.es.js';
|
|
@@ -18,7 +18,7 @@ import { SignalsLoadingSkeleton, SignalsFrameLoadingSkeleton } from './signals-l
|
|
|
18
18
|
import { SnapshotTimeline } from './snapshot-timeline.es.js';
|
|
19
19
|
import { ThemeCompare } from './theme-compare.es.js';
|
|
20
20
|
import { ThemeDetailPanel } from './theme-detail-panel.es.js';
|
|
21
|
-
import { buildDrilledThemeFlow, findNoiseSelection, findThemeSelection } from './theme-drilldown-data.es.js';
|
|
21
|
+
import { buildDrilledThemeFlow, findSelectionStats, mergeVisibleSignalOrder, findNoiseSelection, findThemeSelection } from './theme-drilldown-data.es.js';
|
|
22
22
|
import { ThemeFilterBanner } from './theme-filter-banner.es.js';
|
|
23
23
|
import { ThemeLifelines } from './theme-lifelines.es.js';
|
|
24
24
|
import { TraceIntelligenceExplainer } from './trace-intelligence-explainer.es.js';
|
|
@@ -51,7 +51,7 @@ function SankeySignals({
|
|
|
51
51
|
const [selectedSnapshotOrdinal, setSelectedSnapshotOrdinal] = useState();
|
|
52
52
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
53
53
|
const [viewMode, setViewMode] = useState("flow");
|
|
54
|
-
const [
|
|
54
|
+
const [drillStack, setDrillStack] = useState([]);
|
|
55
55
|
const [detailSelection, setDetailSelection] = useState();
|
|
56
56
|
const [noiseSignalName, setNoiseSignalName] = useState();
|
|
57
57
|
const matchedSnapshotIndex = snapshots.findIndex((snapshot2) => snapshot2.ordinal === selectedSnapshotOrdinal);
|
|
@@ -68,6 +68,7 @@ function SankeySignals({
|
|
|
68
68
|
setIsPlaying(nextIsPlaying);
|
|
69
69
|
};
|
|
70
70
|
const openThemeDetailsAt = (selection, snapshotIndex) => {
|
|
71
|
+
if (selection.kind !== "theme") return;
|
|
71
72
|
selectSnapshot(snapshotIndex);
|
|
72
73
|
setNoiseSignalName(void 0);
|
|
73
74
|
setDetailSelection(selection);
|
|
@@ -91,19 +92,19 @@ function SankeySignals({
|
|
|
91
92
|
entityType,
|
|
92
93
|
signalNames,
|
|
93
94
|
snapshot?.snapshotId,
|
|
94
|
-
drillInAvailable
|
|
95
|
+
drillInAvailable && drillStack.length > 0
|
|
95
96
|
);
|
|
96
97
|
const flow = useMemo(() => {
|
|
97
|
-
if (!stableUnfilteredFlow ||
|
|
98
|
-
const drilledFlow = buildDrilledThemeFlow(stableUnfilteredFlow, pathsQuery.data,
|
|
98
|
+
if (!stableUnfilteredFlow || drillStack.length === 0 || !pathsQuery.data) return stableUnfilteredFlow;
|
|
99
|
+
const drilledFlow = buildDrilledThemeFlow(stableUnfilteredFlow, pathsQuery.data, drillStack);
|
|
99
100
|
return stabilizeThemeFlow(drilledFlow, [stableUnfilteredFlow, drilledFlow]);
|
|
100
|
-
}, [
|
|
101
|
+
}, [drillStack, pathsQuery.data, stableUnfilteredFlow]);
|
|
101
102
|
const graphSummary = useMemo(() => flow ? buildSignalGraphSummary(flow) : void 0, [flow]);
|
|
102
103
|
const populatedStageCount = currentFlow?.stages.filter((stage) => stage.nodes.length > 0).length ?? 0;
|
|
103
104
|
const shouldLoadProgress = snapshotsQuery.isSuccess && !snapshotsQuery.isError && (!snapshot || Boolean(currentFlow && (!flow || !graphSummary || populatedStageCount < 2)));
|
|
104
105
|
const progressQuery = useEntityLearningProgress(entityId, entityType, shouldLoadProgress);
|
|
105
|
-
const isPlaybackBlockedByDrillIn =
|
|
106
|
-
const hasActivePathsError =
|
|
106
|
+
const isPlaybackBlockedByDrillIn = drillStack.length > 0 && (pathsQuery.isFetching || pathsQuery.isError);
|
|
107
|
+
const hasActivePathsError = drillStack.length > 0 && pathsQuery.isError;
|
|
107
108
|
useSnapshotPlayback({
|
|
108
109
|
isPlaying,
|
|
109
110
|
isPlaybackBlocked: isFlowWindowBusy || isPlaybackBlockedByDrillIn,
|
|
@@ -144,7 +145,7 @@ function SankeySignals({
|
|
|
144
145
|
})
|
|
145
146
|
)
|
|
146
147
|
);
|
|
147
|
-
if (
|
|
148
|
+
if (drillStack.length > 0 && nextSnapshot && nextSnapshot.traceCount <= DRILL_IN_TRACE_LIMIT) {
|
|
148
149
|
await queryClient.fetchQuery({
|
|
149
150
|
queryKey: [
|
|
150
151
|
"entity-learning",
|
|
@@ -183,9 +184,9 @@ function SankeySignals({
|
|
|
183
184
|
setIsPlaying(false);
|
|
184
185
|
void snapshotsQuery.refetch();
|
|
185
186
|
void Promise.all(flowQueries.map((query) => query.refetch()));
|
|
186
|
-
if (
|
|
187
|
+
if (drillStack.length > 0 && drillInAvailable) void pathsQuery.refetch();
|
|
187
188
|
},
|
|
188
|
-
onClear: hasActivePathsError ? () =>
|
|
189
|
+
onClear: hasActivePathsError ? () => setDrillStack([]) : void 0
|
|
189
190
|
}
|
|
190
191
|
)
|
|
191
192
|
] });
|
|
@@ -223,28 +224,32 @@ function SankeySignals({
|
|
|
223
224
|
const stages = flow.stages;
|
|
224
225
|
const isNodeClickable = (selection) => findNoiseSelection(flow, selection.column.id, selection.value) !== void 0 || findThemeSelection(flow, selection.column.id, selection.value) !== void 0;
|
|
225
226
|
const handleNodeClick = (selection) => {
|
|
226
|
-
const
|
|
227
|
-
if (
|
|
227
|
+
const nextSelection = findNoiseSelection(flow, selection.column.id, selection.value) ?? findThemeSelection(flow, selection.column.id, selection.value);
|
|
228
|
+
if (!nextSelection || drillStack.some((filter) => filter.signalName === nextSelection.signalName)) return;
|
|
229
|
+
if (nextSelection.kind === "theme") {
|
|
230
|
+
setNoiseSignalName(void 0);
|
|
231
|
+
setDetailSelection(nextSelection);
|
|
232
|
+
if (drillInAvailable) setDrillStack((current) => [...current, nextSelection]);
|
|
233
|
+
} else {
|
|
228
234
|
setDetailSelection(void 0);
|
|
229
|
-
setNoiseSignalName(
|
|
230
|
-
return;
|
|
235
|
+
setNoiseSignalName(nextSelection.signalName);
|
|
231
236
|
}
|
|
232
|
-
const nextSelection = findThemeSelection(flow, selection.column.id, selection.value);
|
|
233
|
-
if (!nextSelection) return;
|
|
234
|
-
setNoiseSignalName(void 0);
|
|
235
|
-
setDetailSelection(nextSelection);
|
|
236
|
-
if (drillInAvailable) setDrillIn(nextSelection);
|
|
237
237
|
};
|
|
238
238
|
const drillInDisabledReason = drillInAvailable ? void 0 : "Drill-in is unavailable for snapshots with more than 2,000 traces.";
|
|
239
|
-
const isDrilledEmpty =
|
|
239
|
+
const isDrilledEmpty = drillStack.length > 0 && pathsQuery.data !== void 0 && flow.snapshot.traceCount === 0;
|
|
240
240
|
const handleSignalOrderChange = (nextSignalNames) => {
|
|
241
241
|
if (perspectiveMutation.isPending) return;
|
|
242
242
|
setIsPlaying(false);
|
|
243
243
|
setDetailSelection(void 0);
|
|
244
244
|
setNoiseSignalName(void 0);
|
|
245
|
-
|
|
246
|
-
|
|
245
|
+
const mergedSignalNames = mergeVisibleSignalOrder(signalNames, nextSignalNames);
|
|
246
|
+
setPendingSignalNames(mergedSignalNames);
|
|
247
|
+
perspectiveMutation.mutate(mergedSignalNames);
|
|
247
248
|
};
|
|
249
|
+
const filtersResolved = drillStack.length > 0 && drillInAvailable && pathsQuery.data !== void 0;
|
|
250
|
+
const detailStats = filtersResolved ? findSelectionStats(flow, drillStack, detailSelection) : void 0;
|
|
251
|
+
const noiseStats = filtersResolved ? findSelectionStats(flow, drillStack, noiseSignalName ? { kind: "noise", signalName: noiseSignalName } : void 0) : void 0;
|
|
252
|
+
const filterKey = serializeThemeFilters(drillStack);
|
|
248
253
|
return /* @__PURE__ */ jsxs("main", { className: "min-w-0 space-y-5 p-4 lg:p-6", children: [
|
|
249
254
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-center justify-between gap-3", children: [
|
|
250
255
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-4", children: [
|
|
@@ -296,26 +301,33 @@ function SankeySignals({
|
|
|
296
301
|
snapshots,
|
|
297
302
|
selectedIndex: selectedSnapshotIndex,
|
|
298
303
|
totalSnapshots,
|
|
299
|
-
summary: `${
|
|
304
|
+
summary: `${drillStack.length > 0 ? drillInAvailable ? "Filtered · " : "Filters unavailable · " : ""}${snapshotSummaryLabel(snapshot, flow)}`,
|
|
300
305
|
isPlaying,
|
|
301
306
|
onPlayingChange: handlePlayingChange,
|
|
302
307
|
onSnapshotChange: selectSnapshot
|
|
303
308
|
}
|
|
304
309
|
),
|
|
305
|
-
|
|
310
|
+
drillStack.length > 0 ? /* @__PURE__ */ jsx(
|
|
306
311
|
ThemeFilterBanner,
|
|
307
312
|
{
|
|
308
|
-
|
|
309
|
-
filteredTraceCount:
|
|
310
|
-
totalTraceCount: currentFlow.
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
313
|
+
selections: drillStack,
|
|
314
|
+
filteredTraceCount: filtersResolved ? flow.snapshot.traceCount : void 0,
|
|
315
|
+
totalTraceCount: currentFlow.snapshot.traceCount,
|
|
316
|
+
isUnavailable: !drillInAvailable,
|
|
317
|
+
onViewDetails: (selection) => {
|
|
318
|
+
if (selection.kind === "theme") {
|
|
319
|
+
setNoiseSignalName(void 0);
|
|
320
|
+
setDetailSelection(selection);
|
|
321
|
+
} else {
|
|
322
|
+
setDetailSelection(void 0);
|
|
323
|
+
setNoiseSignalName(selection.signalName);
|
|
324
|
+
}
|
|
314
325
|
},
|
|
315
|
-
|
|
326
|
+
onRemove: (signalName) => setDrillStack((current) => current.filter((filter) => filter.signalName !== signalName)),
|
|
327
|
+
onClear: () => setDrillStack([])
|
|
316
328
|
}
|
|
317
329
|
) : null,
|
|
318
|
-
|
|
330
|
+
isDrilledEmpty ? /* @__PURE__ */ jsx("section", { className: "border-border1 bg-surface2 text-neutral3 rounded-lg border p-6 text-sm", children: "This theme is not present in the selected snapshot. Use the clear filter action above to return to the full flow." }) : graphSummary.records.length === 0 ? /* @__PURE__ */ jsx("section", { className: "border-border1 bg-surface2 text-neutral3 rounded-lg border p-6 text-sm", children: "No cross-signal flow for this snapshot — its trace signals have not overlapped on shared traces yet. Pick another snapshot from the timeline below." }) : /* @__PURE__ */ jsx(
|
|
319
331
|
FlowCard,
|
|
320
332
|
{
|
|
321
333
|
columns: graphSummary.columns,
|
|
@@ -341,9 +353,11 @@ function SankeySignals({
|
|
|
341
353
|
snapshotId: snapshot.snapshotId,
|
|
342
354
|
snapshotTotal: snapshot.total,
|
|
343
355
|
selection: detailSelection,
|
|
356
|
+
filters: drillStack,
|
|
357
|
+
filteredStats: detailStats,
|
|
344
358
|
onClose: () => setDetailSelection(void 0)
|
|
345
359
|
},
|
|
346
|
-
`${snapshot.snapshotId}:${detailSelection?.signalName ?? ""}:${detailSelection?.themeId ?? ""}`
|
|
360
|
+
`${snapshot.snapshotId}:${detailSelection?.signalName ?? ""}:${detailSelection?.themeId ?? ""}:${filterKey}`
|
|
347
361
|
),
|
|
348
362
|
/* @__PURE__ */ jsx(
|
|
349
363
|
NoiseDetailPanel,
|
|
@@ -352,9 +366,11 @@ function SankeySignals({
|
|
|
352
366
|
entityType,
|
|
353
367
|
snapshotId: snapshot.snapshotId,
|
|
354
368
|
signalName: noiseSignalName,
|
|
369
|
+
filters: drillStack,
|
|
370
|
+
filteredStats: noiseStats,
|
|
355
371
|
onClose: () => setNoiseSignalName(void 0)
|
|
356
372
|
},
|
|
357
|
-
`${snapshot.snapshotId}:${noiseSignalName ?? ""}`
|
|
373
|
+
`${snapshot.snapshotId}:${noiseSignalName ?? ""}:${filterKey}`
|
|
358
374
|
)
|
|
359
375
|
] });
|
|
360
376
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sankey-signals.es.js","sources":["../../../src/ee/signals/sankey-signals.tsx"],"sourcesContent":["import { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { ArrowLeftRight, ChartNoAxesGantt, Waypoints } from 'lucide-react';\nimport { useMemo, useState } from 'react';\n\nimport { SignalsOverviewPage as SignalsEmptyState } from './components/signals-overview-page';\nimport { fetchThemeFlow, fetchThemePaths, fetchThemeSnapshots } from './entity-learning-api';\nimport { FlowCard } from './flow-card';\nimport { useEntityLearningProgress } from './hooks/use-entity-learning-progress';\nimport { useSnapshotPlayback } from './hooks/use-snapshot-playback';\nimport { useThemeFlows } from './hooks/use-theme-flows';\nimport { useThemePaths } from './hooks/use-theme-paths';\nimport { useThemeSnapshots } from './hooks/use-theme-snapshots';\nimport { NoiseDetailPanel } from './noise-detail-panel';\nimport {\n buildSignalGraphSummary,\n selectFlowSnapshotIds,\n snapshotSummaryLabel,\n stabilizeThemeFlow,\n} from './sankey-signals-data';\nimport { SIGNAL_PROCESSING_ORDER } from './signal-formatting';\nimport { SignalsErrorState } from './signals-error-state';\nimport { SignalsFrameLoadingSkeleton, SignalsLoadingSkeleton } from './signals-loading-skeleton';\nimport { SnapshotTimeline } from './snapshot-timeline';\nimport { ThemeCompare } from './theme-compare';\nimport { ThemeDetailPanel } from './theme-detail-panel';\nimport { buildDrilledThemeFlow, findNoiseSelection, findThemeSelection } from './theme-drilldown-data';\nimport type { ThemeSelection } from './theme-drilldown-data';\nimport { ThemeFilterBanner } from './theme-filter-banner';\nimport { ThemeLifelines } from './theme-lifelines';\nimport { TraceIntelligenceExplainer } from './trace-intelligence-explainer';\nimport type { TraceSignalName } from './types';\nimport { useTraceIntelligence } from './use-trace-intelligence';\nimport { ViewModeTab } from './view-mode-tab';\nimport type { SignalsViewMode } from './view-mode-tab';\nimport type { SankeyChartNodeSelection } from '@/ds/components/SankeyChart';\nimport { TabList, Tabs } from '@/ds/components/Tabs';\n\nexport interface SankeySignalsProps {\n entityId: string;\n entityType?: string;\n signalNames: TraceSignalName[];\n dateFrom?: Date;\n dateTo?: Date;\n height?: number;\n /** Date range control rendered in line with the view mode tabs. */\n dateRangePicker?: React.ReactNode;\n}\n\nconst DRILL_IN_TRACE_LIMIT = 2000;\nconst FLOW_SIGNAL_LIST = `${SIGNAL_PROCESSING_ORDER.slice(0, -1).join(', ')}, and ${SIGNAL_PROCESSING_ORDER[SIGNAL_PROCESSING_ORDER.length - 1]}`;\n\n/** One-line answer to \"what am I looking at?\" for each view, shown under the tabs. */\nconst VIEW_DESCRIPTIONS: Record<SignalsViewMode, string> = {\n flow: `How this agent's traces distribute across ${FLOW_SIGNAL_LIST} themes at this point in time.`,\n compare: 'Which themes grew, shrank, appeared, or disappeared between two points in time.',\n lifelines: \"Each theme's share of traces across the whole selected range.\",\n};\n\nexport function SankeySignals({\n entityId,\n entityType = 'agent',\n signalNames: initialSignalNames,\n dateFrom,\n dateTo,\n height,\n dateRangePicker,\n}: SankeySignalsProps) {\n const queryClient = useQueryClient();\n const { cacheScope, request, LinkComponent } = useTraceIntelligence();\n const [signalNames, setSignalNames] = useState(() => initialSignalNames);\n const [pendingSignalNames, setPendingSignalNames] = useState<TraceSignalName[]>();\n const snapshotsQuery = useThemeSnapshots(entityId, entityType, signalNames, dateFrom, dateTo);\n const snapshots = [...(snapshotsQuery.data?.snapshots ?? [])].sort((left, right) => left.ordinal - right.ordinal);\n const [selectedSnapshotOrdinal, setSelectedSnapshotOrdinal] = useState<number>();\n const [isPlaying, setIsPlaying] = useState(false);\n const [viewMode, setViewMode] = useState<SignalsViewMode>('flow');\n const [drillIn, setDrillIn] = useState<ThemeSelection>();\n const [detailSelection, setDetailSelection] = useState<ThemeSelection>();\n const [noiseSignalName, setNoiseSignalName] = useState<TraceSignalName>();\n const matchedSnapshotIndex = snapshots.findIndex(snapshot => snapshot.ordinal === selectedSnapshotOrdinal);\n const selectedSnapshotIndex = matchedSnapshotIndex >= 0 ? matchedSnapshotIndex : 0;\n const snapshot = snapshots[selectedSnapshotIndex];\n const totalSnapshots = snapshotsQuery.data?.totalSnapshots ?? snapshot?.total ?? 0;\n const selectSnapshot = (index: number) => setSelectedSnapshotOrdinal(snapshots[index]?.ordinal);\n const handleViewModeChange = (nextViewMode: SignalsViewMode) => {\n if (nextViewMode !== 'flow') setIsPlaying(false);\n setViewMode(nextViewMode);\n };\n const handlePlayingChange = (nextIsPlaying: boolean) => {\n // Restart from the first landmark when play is pressed at the end.\n if (nextIsPlaying && selectedSnapshotIndex === snapshots.length - 1) selectSnapshot(0);\n setIsPlaying(nextIsPlaying);\n };\n // Compare cards and lifeline points open details for the theme at the\n // landmark they were clicked on, so the panel's snapshot follows the click.\n const openThemeDetailsAt = (selection: ThemeSelection, snapshotIndex: number) => {\n selectSnapshot(snapshotIndex);\n setNoiseSignalName(undefined);\n setDetailSelection(selection);\n };\n\n // Undefined at the last landmark so playback stops instead of looping.\n const nextSnapshotOrdinal = snapshots[selectedSnapshotIndex + 1]?.ordinal;\n const flowSnapshotIds = selectFlowSnapshotIds(snapshots, selectedSnapshotIndex);\n const flowQueries = useThemeFlows(entityId, entityType, signalNames, flowSnapshotIds);\n const flowQuery = flowQueries[flowSnapshotIds.indexOf(snapshot?.snapshotId ?? '')];\n const currentFlow = flowQuery?.data;\n // The loading skeleton tracks only the selected snapshot's flow; prefetched\n // neighbors warm the cache in the background without blocking the chart.\n const isFlowPending = flowQuery?.isPending ?? false;\n // Errors stay window-wide: a failed preload surfaces the retry state instead\n // of letting playback advance into a broken frame.\n const hasFlowError = flowQueries.some(query => query.isError);\n const isFlowWindowBusy = flowQueries.some(query => query.isPending) || hasFlowError;\n const windowFlows = useMemo(() => flowQueries.flatMap(query => (query.data ? [query.data] : [])), [flowQueries]);\n const stableUnfilteredFlow = useMemo(\n () => (currentFlow ? stabilizeThemeFlow(currentFlow, windowFlows) : undefined),\n [currentFlow, windowFlows],\n );\n const drillInAvailable = Boolean(currentFlow && currentFlow.snapshot.traceCount <= DRILL_IN_TRACE_LIMIT);\n const pathsQuery = useThemePaths(\n entityId,\n entityType,\n signalNames,\n snapshot?.snapshotId,\n drillInAvailable ? drillIn?.themeId : undefined,\n );\n const flow = useMemo(() => {\n if (!stableUnfilteredFlow || !drillIn || !pathsQuery.data) return stableUnfilteredFlow;\n\n const drilledFlow = buildDrilledThemeFlow(stableUnfilteredFlow, pathsQuery.data, drillIn);\n return stabilizeThemeFlow(drilledFlow, [stableUnfilteredFlow, drilledFlow]);\n }, [drillIn, pathsQuery.data, stableUnfilteredFlow]);\n const graphSummary = useMemo(() => (flow ? buildSignalGraphSummary(flow) : undefined), [flow]);\n const populatedStageCount = currentFlow?.stages.filter(stage => stage.nodes.length > 0).length ?? 0;\n const shouldLoadProgress =\n snapshotsQuery.isSuccess &&\n !snapshotsQuery.isError &&\n (!snapshot || Boolean(currentFlow && (!flow || !graphSummary || populatedStageCount < 2)));\n const progressQuery = useEntityLearningProgress(entityId, entityType, shouldLoadProgress);\n const isPlaybackBlockedByDrillIn = drillIn !== undefined && (pathsQuery.isFetching || pathsQuery.isError);\n const hasActivePathsError = drillIn !== undefined && pathsQuery.isError;\n\n useSnapshotPlayback({\n isPlaying,\n isPlaybackBlocked: isFlowWindowBusy || isPlaybackBlockedByDrillIn,\n nextSnapshot: nextSnapshotOrdinal,\n onAdvance: ordinal => {\n if (ordinal === undefined) {\n setIsPlaying(false);\n return;\n }\n setSelectedSnapshotOrdinal(ordinal);\n },\n snapshotCount: snapshots.length,\n });\n\n const perspectiveMutation = useMutation({\n mutationFn: async (nextSignalNames: TraceSignalName[]) => {\n const nextSnapshots = await queryClient.fetchQuery({\n queryKey: [\n 'entity-learning',\n cacheScope,\n entityType,\n entityId,\n 'theme-snapshots',\n nextSignalNames,\n dateFrom?.toISOString(),\n dateTo?.toISOString(),\n ],\n queryFn: () => fetchThemeSnapshots(request, entityId, entityType, nextSignalNames, dateFrom, dateTo),\n });\n const sortedNextSnapshots = [...nextSnapshots.snapshots].sort((left, right) => left.ordinal - right.ordinal);\n const matchedNextIndex = sortedNextSnapshots.findIndex(candidate => candidate.ordinal === snapshot?.ordinal);\n const nextSelectedIndex = matchedNextIndex >= 0 ? matchedNextIndex : 0;\n const nextSnapshot = sortedNextSnapshots[nextSelectedIndex];\n await Promise.all(\n selectFlowSnapshotIds(sortedNextSnapshots, nextSelectedIndex).map(snapshotId =>\n queryClient.fetchQuery({\n queryKey: ['entity-learning', cacheScope, entityType, entityId, 'theme-flow', nextSignalNames, snapshotId],\n queryFn: () => fetchThemeFlow(request, entityId, entityType, nextSignalNames, snapshotId),\n }),\n ),\n );\n if (drillIn && nextSnapshot && nextSnapshot.traceCount <= DRILL_IN_TRACE_LIMIT) {\n await queryClient.fetchQuery({\n queryKey: [\n 'entity-learning',\n cacheScope,\n entityType,\n entityId,\n 'theme-paths',\n nextSignalNames,\n nextSnapshot.snapshotId,\n ],\n queryFn: () => fetchThemePaths(request, entityId, entityType, nextSignalNames, nextSnapshot.snapshotId),\n });\n }\n return nextSignalNames;\n },\n onSuccess: nextSignalNames => {\n setSignalNames(nextSignalNames);\n setPendingSignalNames(undefined);\n },\n onError: () => setPendingSignalNames(undefined),\n });\n\n if (snapshotsQuery.isPending) {\n return (\n <>\n {dateRangePicker && <div className=\"flex justify-end px-4 pt-4 lg:px-6 lg:pt-6\">{dateRangePicker}</div>}\n <SignalsLoadingSkeleton />\n </>\n );\n }\n\n if (snapshotsQuery.isError || hasFlowError || hasActivePathsError) {\n return (\n <>\n {dateRangePicker && <div className=\"flex justify-end px-4 pt-4 lg:px-6 lg:pt-6\">{dateRangePicker}</div>}\n <SignalsErrorState\n message=\"Unable to load trace signal flow.\"\n onRetry={() => {\n setIsPlaying(false);\n void snapshotsQuery.refetch();\n void Promise.all(flowQueries.map(query => query.refetch()));\n if (drillIn && drillInAvailable) void pathsQuery.refetch();\n }}\n onClear={hasActivePathsError ? () => setDrillIn(undefined) : undefined}\n />\n </>\n );\n }\n\n if (!snapshot) {\n return (\n <>\n {dateRangePicker && <div className=\"flex justify-end px-4 pt-4 lg:px-6 lg:pt-6\">{dateRangePicker}</div>}\n <SignalsEmptyState LinkComponent={LinkComponent} progress={progressQuery.data} isRangeEmpty />\n </>\n );\n }\n\n if (isFlowPending) {\n return (\n <main className=\"min-w-0 space-y-5 p-4 lg:p-6\">\n {dateRangePicker && <div className=\"flex justify-end\">{dateRangePicker}</div>}\n <SnapshotTimeline\n snapshots={snapshots}\n selectedIndex={selectedSnapshotIndex}\n totalSnapshots={totalSnapshots}\n summary={snapshot ? snapshotSummaryLabel(snapshot, undefined) : ''}\n isPlaying={isPlaying}\n onPlayingChange={handlePlayingChange}\n onSnapshotChange={selectSnapshot}\n />\n <SignalsFrameLoadingSkeleton />\n </main>\n );\n }\n\n if (!currentFlow || !flow || !graphSummary || populatedStageCount < 2) {\n return (\n <>\n {dateRangePicker && <div className=\"flex justify-end px-4 pt-4 lg:px-6 lg:pt-6\">{dateRangePicker}</div>}\n <SignalsEmptyState LinkComponent={LinkComponent} progress={progressQuery.data} />\n </>\n );\n }\n\n const stages = flow.stages;\n // Noise nodes open the noise details panel (noise has no themeId, so it\n // cannot drill in). Theme nodes always open details; they additionally\n // isolate the flow when the snapshot is under the drill-in limit.\n const isNodeClickable = (selection: SankeyChartNodeSelection) =>\n findNoiseSelection(flow, selection.column.id, selection.value) !== undefined ||\n findThemeSelection(flow, selection.column.id, selection.value) !== undefined;\n const handleNodeClick = (selection: SankeyChartNodeSelection) => {\n const noiseSignal = findNoiseSelection(flow, selection.column.id, selection.value);\n if (noiseSignal) {\n setDetailSelection(undefined);\n setNoiseSignalName(noiseSignal);\n return;\n }\n const nextSelection = findThemeSelection(flow, selection.column.id, selection.value);\n if (!nextSelection) return;\n setNoiseSignalName(undefined);\n setDetailSelection(nextSelection);\n if (drillInAvailable) setDrillIn(nextSelection);\n };\n const drillInDisabledReason = drillInAvailable\n ? undefined\n : 'Drill-in is unavailable for snapshots with more than 2,000 traces.';\n const isDrilledEmpty = drillIn !== undefined && pathsQuery.data !== undefined && flow.snapshot.traceCount === 0;\n const handleSignalOrderChange = (nextSignalNames: TraceSignalName[]) => {\n if (perspectiveMutation.isPending) return;\n setIsPlaying(false);\n setDetailSelection(undefined);\n setNoiseSignalName(undefined);\n setPendingSignalNames(nextSignalNames);\n perspectiveMutation.mutate(nextSignalNames);\n };\n\n return (\n <main className=\"min-w-0 space-y-5 p-4 lg:p-6\">\n <div className=\"flex min-w-0 flex-wrap items-center justify-between gap-3\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-4\">\n <Tabs<SignalsViewMode>\n value={viewMode}\n defaultTab=\"flow\"\n onValueChange={handleViewModeChange}\n className=\"w-fit\"\n >\n <TabList variant=\"pill-ghost\">\n <ViewModeTab value=\"flow\" icon={<Waypoints />} label=\"Flow\" />\n <ViewModeTab value=\"compare\" icon={<ArrowLeftRight />} label=\"Compare\" />\n <ViewModeTab value=\"lifelines\" icon={<ChartNoAxesGantt />} label=\"Lifelines\" />\n </TabList>\n </Tabs>\n <TraceIntelligenceExplainer />\n </div>\n {dateRangePicker}\n </div>\n <p className=\"text-neutral3 text-xs\">{VIEW_DESCRIPTIONS[viewMode]}</p>\n {viewMode === 'compare' ? (\n <ThemeCompare\n entityId={entityId}\n entityType={entityType}\n signalNames={signalNames}\n snapshots={snapshots}\n totalSnapshots={totalSnapshots}\n onThemeSelect={openThemeDetailsAt}\n />\n ) : viewMode === 'lifelines' ? (\n <ThemeLifelines\n entityId={entityId}\n entityType={entityType}\n signalNames={signalNames}\n snapshots={snapshots}\n totalSnapshots={totalSnapshots}\n selectedIndex={selectedSnapshotIndex}\n onSnapshotSelect={selectSnapshot}\n onThemeSelect={openThemeDetailsAt}\n />\n ) : (\n <>\n <SnapshotTimeline\n snapshots={snapshots}\n selectedIndex={selectedSnapshotIndex}\n totalSnapshots={totalSnapshots}\n summary={`${drillIn ? 'Filtered · ' : ''}${snapshotSummaryLabel(snapshot, flow)}`}\n isPlaying={isPlaying}\n onPlayingChange={handlePlayingChange}\n onSnapshotChange={selectSnapshot}\n />\n {drillIn ? (\n <ThemeFilterBanner\n selection={drillIn}\n filteredTraceCount={pathsQuery.data ? flow.stages[0]?.traceCount : undefined}\n totalTraceCount={currentFlow.stages[0]?.traceCount ?? currentFlow.snapshot.traceCount}\n onViewDetails={() => {\n setNoiseSignalName(undefined);\n setDetailSelection(drillIn);\n }}\n onClear={() => setDrillIn(undefined)}\n />\n ) : null}\n {drillIn && !drillInAvailable ? (\n <section className=\"border-border1 bg-surface2 text-neutral3 rounded-lg border p-6 text-sm\">\n This drill-in is unavailable for snapshots with more than 2,000 traces. Use the clear filter action above\n or choose another snapshot.\n </section>\n ) : drillIn && pathsQuery.isPending ? (\n <SignalsFrameLoadingSkeleton />\n ) : isDrilledEmpty ? (\n <section className=\"border-border1 bg-surface2 text-neutral3 rounded-lg border p-6 text-sm\">\n This theme is not present in the selected snapshot. Use the clear filter action above to return to the\n full flow.\n </section>\n ) : graphSummary.records.length === 0 ? (\n <section className=\"border-border1 bg-surface2 text-neutral3 rounded-lg border p-6 text-sm\">\n No cross-signal flow for this snapshot — its trace signals have not overlapped on shared traces yet. Pick\n another snapshot from the timeline below.\n </section>\n ) : (\n <FlowCard\n columns={graphSummary.columns}\n records={graphSummary.records}\n stages={stages}\n height={height}\n onNodeClick={handleNodeClick}\n isNodeClickable={isNodeClickable}\n drillInDisabledReason={drillInDisabledReason}\n onOrderChange={handleSignalOrderChange}\n signalOrder={pendingSignalNames ?? signalNames}\n reorderDisabled={perspectiveMutation.isPending}\n />\n )}\n {perspectiveMutation.isPending ? (\n <p className=\"text-neutral3 font-mono text-xs\" role=\"status\">\n Reloading snapshots for new trace signal perspective…\n </p>\n ) : null}\n {perspectiveMutation.isError ? (\n <p className=\"text-xs text-red-500\" role=\"alert\">\n Unable to load that trace signal perspective. Try reordering the columns again.\n </p>\n ) : null}\n </>\n )}\n <ThemeDetailPanel\n key={`${snapshot.snapshotId}:${detailSelection?.signalName ?? ''}:${detailSelection?.themeId ?? ''}`}\n entityId={entityId}\n entityType={entityType}\n snapshotId={snapshot.snapshotId}\n snapshotTotal={snapshot.total}\n selection={detailSelection}\n onClose={() => setDetailSelection(undefined)}\n />\n <NoiseDetailPanel\n key={`${snapshot.snapshotId}:${noiseSignalName ?? ''}`}\n entityId={entityId}\n entityType={entityType}\n snapshotId={snapshot.snapshotId}\n signalName={noiseSignalName}\n onClose={() => setNoiseSignalName(undefined)}\n />\n </main>\n );\n}\n"],"names":["snapshot","SignalsEmptyState"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sankey-signals.es.js","sources":["../../../src/ee/signals/sankey-signals.tsx"],"sourcesContent":["import { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { ArrowLeftRight, ChartNoAxesGantt, Waypoints } from 'lucide-react';\nimport { useMemo, useState } from 'react';\n\nimport { SignalsOverviewPage as SignalsEmptyState } from './components/signals-overview-page';\nimport { fetchThemeFlow, fetchThemePaths, fetchThemeSnapshots, serializeThemeFilters } from './entity-learning-api';\nimport { FlowCard } from './flow-card';\nimport { useEntityLearningProgress } from './hooks/use-entity-learning-progress';\nimport { useSnapshotPlayback } from './hooks/use-snapshot-playback';\nimport { useThemeFlows } from './hooks/use-theme-flows';\nimport { useThemePaths } from './hooks/use-theme-paths';\nimport { useThemeSnapshots } from './hooks/use-theme-snapshots';\nimport { NoiseDetailPanel } from './noise-detail-panel';\nimport {\n buildSignalGraphSummary,\n selectFlowSnapshotIds,\n snapshotSummaryLabel,\n stabilizeThemeFlow,\n} from './sankey-signals-data';\nimport { SIGNAL_PROCESSING_ORDER } from './signal-formatting';\nimport { SignalsErrorState } from './signals-error-state';\nimport { SignalsFrameLoadingSkeleton, SignalsLoadingSkeleton } from './signals-loading-skeleton';\nimport { SnapshotTimeline } from './snapshot-timeline';\nimport { ThemeCompare } from './theme-compare';\nimport { ThemeDetailPanel } from './theme-detail-panel';\nimport {\n buildDrilledThemeFlow,\n findNoiseSelection,\n findSelectionStats,\n findThemeSelection,\n mergeVisibleSignalOrder,\n} from './theme-drilldown-data';\nimport type { SelectedTheme, ThemeSelection } from './theme-drilldown-data';\nimport { ThemeFilterBanner } from './theme-filter-banner';\nimport { ThemeLifelines } from './theme-lifelines';\nimport { TraceIntelligenceExplainer } from './trace-intelligence-explainer';\nimport type { TraceSignalName } from './types';\nimport { useTraceIntelligence } from './use-trace-intelligence';\nimport { ViewModeTab } from './view-mode-tab';\nimport type { SignalsViewMode } from './view-mode-tab';\nimport type { SankeyChartNodeSelection } from '@/ds/components/SankeyChart';\nimport { TabList, Tabs } from '@/ds/components/Tabs';\n\nexport interface SankeySignalsProps {\n entityId: string;\n entityType?: string;\n signalNames: TraceSignalName[];\n dateFrom?: Date;\n dateTo?: Date;\n height?: number;\n /** Date range control rendered in line with the view mode tabs. */\n dateRangePicker?: React.ReactNode;\n}\n\nconst DRILL_IN_TRACE_LIMIT = 2000;\nconst FLOW_SIGNAL_LIST = `${SIGNAL_PROCESSING_ORDER.slice(0, -1).join(', ')}, and ${SIGNAL_PROCESSING_ORDER[SIGNAL_PROCESSING_ORDER.length - 1]}`;\n\n/** One-line answer to \"what am I looking at?\" for each view, shown under the tabs. */\nconst VIEW_DESCRIPTIONS: Record<SignalsViewMode, string> = {\n flow: `How this agent's traces distribute across ${FLOW_SIGNAL_LIST} themes at this point in time.`,\n compare: 'Which themes grew, shrank, appeared, or disappeared between two points in time.',\n lifelines: \"Each theme's share of traces across the whole selected range.\",\n};\n\nexport function SankeySignals({\n entityId,\n entityType = 'agent',\n signalNames: initialSignalNames,\n dateFrom,\n dateTo,\n height,\n dateRangePicker,\n}: SankeySignalsProps) {\n const queryClient = useQueryClient();\n const { cacheScope, request, LinkComponent } = useTraceIntelligence();\n const [signalNames, setSignalNames] = useState(() => initialSignalNames);\n const [pendingSignalNames, setPendingSignalNames] = useState<TraceSignalName[]>();\n const snapshotsQuery = useThemeSnapshots(entityId, entityType, signalNames, dateFrom, dateTo);\n const snapshots = [...(snapshotsQuery.data?.snapshots ?? [])].sort((left, right) => left.ordinal - right.ordinal);\n const [selectedSnapshotOrdinal, setSelectedSnapshotOrdinal] = useState<number>();\n const [isPlaying, setIsPlaying] = useState(false);\n const [viewMode, setViewMode] = useState<SignalsViewMode>('flow');\n const [drillStack, setDrillStack] = useState<ThemeSelection[]>([]);\n const [detailSelection, setDetailSelection] = useState<SelectedTheme>();\n const [noiseSignalName, setNoiseSignalName] = useState<TraceSignalName>();\n const matchedSnapshotIndex = snapshots.findIndex(snapshot => snapshot.ordinal === selectedSnapshotOrdinal);\n const selectedSnapshotIndex = matchedSnapshotIndex >= 0 ? matchedSnapshotIndex : 0;\n const snapshot = snapshots[selectedSnapshotIndex];\n const totalSnapshots = snapshotsQuery.data?.totalSnapshots ?? snapshot?.total ?? 0;\n const selectSnapshot = (index: number) => setSelectedSnapshotOrdinal(snapshots[index]?.ordinal);\n const handleViewModeChange = (nextViewMode: SignalsViewMode) => {\n if (nextViewMode !== 'flow') setIsPlaying(false);\n setViewMode(nextViewMode);\n };\n const handlePlayingChange = (nextIsPlaying: boolean) => {\n // Restart from the first landmark when play is pressed at the end.\n if (nextIsPlaying && selectedSnapshotIndex === snapshots.length - 1) selectSnapshot(0);\n setIsPlaying(nextIsPlaying);\n };\n // Compare cards and lifeline points open details for the theme at the\n // landmark they were clicked on, so the panel's snapshot follows the click.\n const openThemeDetailsAt = (selection: ThemeSelection, snapshotIndex: number) => {\n if (selection.kind !== 'theme') return;\n selectSnapshot(snapshotIndex);\n setNoiseSignalName(undefined);\n setDetailSelection(selection);\n };\n\n // Undefined at the last landmark so playback stops instead of looping.\n const nextSnapshotOrdinal = snapshots[selectedSnapshotIndex + 1]?.ordinal;\n const flowSnapshotIds = selectFlowSnapshotIds(snapshots, selectedSnapshotIndex);\n const flowQueries = useThemeFlows(entityId, entityType, signalNames, flowSnapshotIds);\n const flowQuery = flowQueries[flowSnapshotIds.indexOf(snapshot?.snapshotId ?? '')];\n const currentFlow = flowQuery?.data;\n // The loading skeleton tracks only the selected snapshot's flow; prefetched\n // neighbors warm the cache in the background without blocking the chart.\n const isFlowPending = flowQuery?.isPending ?? false;\n // Errors stay window-wide: a failed preload surfaces the retry state instead\n // of letting playback advance into a broken frame.\n const hasFlowError = flowQueries.some(query => query.isError);\n const isFlowWindowBusy = flowQueries.some(query => query.isPending) || hasFlowError;\n const windowFlows = useMemo(() => flowQueries.flatMap(query => (query.data ? [query.data] : [])), [flowQueries]);\n const stableUnfilteredFlow = useMemo(\n () => (currentFlow ? stabilizeThemeFlow(currentFlow, windowFlows) : undefined),\n [currentFlow, windowFlows],\n );\n const drillInAvailable = Boolean(currentFlow && currentFlow.snapshot.traceCount <= DRILL_IN_TRACE_LIMIT);\n const pathsQuery = useThemePaths(\n entityId,\n entityType,\n signalNames,\n snapshot?.snapshotId,\n drillInAvailable && drillStack.length > 0,\n );\n const flow = useMemo(() => {\n if (!stableUnfilteredFlow || drillStack.length === 0 || !pathsQuery.data) return stableUnfilteredFlow;\n\n const drilledFlow = buildDrilledThemeFlow(stableUnfilteredFlow, pathsQuery.data, drillStack);\n return stabilizeThemeFlow(drilledFlow, [stableUnfilteredFlow, drilledFlow]);\n }, [drillStack, pathsQuery.data, stableUnfilteredFlow]);\n const graphSummary = useMemo(() => (flow ? buildSignalGraphSummary(flow) : undefined), [flow]);\n const populatedStageCount = currentFlow?.stages.filter(stage => stage.nodes.length > 0).length ?? 0;\n const shouldLoadProgress =\n snapshotsQuery.isSuccess &&\n !snapshotsQuery.isError &&\n (!snapshot || Boolean(currentFlow && (!flow || !graphSummary || populatedStageCount < 2)));\n const progressQuery = useEntityLearningProgress(entityId, entityType, shouldLoadProgress);\n const isPlaybackBlockedByDrillIn = drillStack.length > 0 && (pathsQuery.isFetching || pathsQuery.isError);\n const hasActivePathsError = drillStack.length > 0 && pathsQuery.isError;\n\n useSnapshotPlayback({\n isPlaying,\n isPlaybackBlocked: isFlowWindowBusy || isPlaybackBlockedByDrillIn,\n nextSnapshot: nextSnapshotOrdinal,\n onAdvance: ordinal => {\n if (ordinal === undefined) {\n setIsPlaying(false);\n return;\n }\n setSelectedSnapshotOrdinal(ordinal);\n },\n snapshotCount: snapshots.length,\n });\n\n const perspectiveMutation = useMutation({\n mutationFn: async (nextSignalNames: TraceSignalName[]) => {\n const nextSnapshots = await queryClient.fetchQuery({\n queryKey: [\n 'entity-learning',\n cacheScope,\n entityType,\n entityId,\n 'theme-snapshots',\n nextSignalNames,\n dateFrom?.toISOString(),\n dateTo?.toISOString(),\n ],\n queryFn: () => fetchThemeSnapshots(request, entityId, entityType, nextSignalNames, dateFrom, dateTo),\n });\n const sortedNextSnapshots = [...nextSnapshots.snapshots].sort((left, right) => left.ordinal - right.ordinal);\n const matchedNextIndex = sortedNextSnapshots.findIndex(candidate => candidate.ordinal === snapshot?.ordinal);\n const nextSelectedIndex = matchedNextIndex >= 0 ? matchedNextIndex : 0;\n const nextSnapshot = sortedNextSnapshots[nextSelectedIndex];\n await Promise.all(\n selectFlowSnapshotIds(sortedNextSnapshots, nextSelectedIndex).map(snapshotId =>\n queryClient.fetchQuery({\n queryKey: ['entity-learning', cacheScope, entityType, entityId, 'theme-flow', nextSignalNames, snapshotId],\n queryFn: () => fetchThemeFlow(request, entityId, entityType, nextSignalNames, snapshotId),\n }),\n ),\n );\n if (drillStack.length > 0 && nextSnapshot && nextSnapshot.traceCount <= DRILL_IN_TRACE_LIMIT) {\n await queryClient.fetchQuery({\n queryKey: [\n 'entity-learning',\n cacheScope,\n entityType,\n entityId,\n 'theme-paths',\n nextSignalNames,\n nextSnapshot.snapshotId,\n ],\n queryFn: () => fetchThemePaths(request, entityId, entityType, nextSignalNames, nextSnapshot.snapshotId),\n });\n }\n return nextSignalNames;\n },\n onSuccess: nextSignalNames => {\n setSignalNames(nextSignalNames);\n setPendingSignalNames(undefined);\n },\n onError: () => setPendingSignalNames(undefined),\n });\n\n if (snapshotsQuery.isPending) {\n return (\n <>\n {dateRangePicker && <div className=\"flex justify-end px-4 pt-4 lg:px-6 lg:pt-6\">{dateRangePicker}</div>}\n <SignalsLoadingSkeleton />\n </>\n );\n }\n\n if (snapshotsQuery.isError || hasFlowError || hasActivePathsError) {\n return (\n <>\n {dateRangePicker && <div className=\"flex justify-end px-4 pt-4 lg:px-6 lg:pt-6\">{dateRangePicker}</div>}\n <SignalsErrorState\n message=\"Unable to load trace signal flow.\"\n onRetry={() => {\n setIsPlaying(false);\n void snapshotsQuery.refetch();\n void Promise.all(flowQueries.map(query => query.refetch()));\n if (drillStack.length > 0 && drillInAvailable) void pathsQuery.refetch();\n }}\n onClear={hasActivePathsError ? () => setDrillStack([]) : undefined}\n />\n </>\n );\n }\n\n if (!snapshot) {\n return (\n <>\n {dateRangePicker && <div className=\"flex justify-end px-4 pt-4 lg:px-6 lg:pt-6\">{dateRangePicker}</div>}\n <SignalsEmptyState LinkComponent={LinkComponent} progress={progressQuery.data} isRangeEmpty />\n </>\n );\n }\n\n if (isFlowPending) {\n return (\n <main className=\"min-w-0 space-y-5 p-4 lg:p-6\">\n {dateRangePicker && <div className=\"flex justify-end\">{dateRangePicker}</div>}\n <SnapshotTimeline\n snapshots={snapshots}\n selectedIndex={selectedSnapshotIndex}\n totalSnapshots={totalSnapshots}\n summary={snapshot ? snapshotSummaryLabel(snapshot, undefined) : ''}\n isPlaying={isPlaying}\n onPlayingChange={handlePlayingChange}\n onSnapshotChange={selectSnapshot}\n />\n <SignalsFrameLoadingSkeleton />\n </main>\n );\n }\n\n if (!currentFlow || !flow || !graphSummary || populatedStageCount < 2) {\n return (\n <>\n {dateRangePicker && <div className=\"flex justify-end px-4 pt-4 lg:px-6 lg:pt-6\">{dateRangePicker}</div>}\n <SignalsEmptyState LinkComponent={LinkComponent} progress={progressQuery.data} />\n </>\n );\n }\n\n const stages = flow.stages;\n const isNodeClickable = (selection: SankeyChartNodeSelection) =>\n findNoiseSelection(flow, selection.column.id, selection.value) !== undefined ||\n findThemeSelection(flow, selection.column.id, selection.value) !== undefined;\n const handleNodeClick = (selection: SankeyChartNodeSelection) => {\n const nextSelection =\n findNoiseSelection(flow, selection.column.id, selection.value) ??\n findThemeSelection(flow, selection.column.id, selection.value);\n if (!nextSelection || drillStack.some(filter => filter.signalName === nextSelection.signalName)) return;\n if (nextSelection.kind === 'theme') {\n setNoiseSignalName(undefined);\n setDetailSelection(nextSelection);\n if (drillInAvailable) setDrillStack(current => [...current, nextSelection]);\n } else {\n setDetailSelection(undefined);\n setNoiseSignalName(nextSelection.signalName);\n }\n };\n const drillInDisabledReason = drillInAvailable\n ? undefined\n : 'Drill-in is unavailable for snapshots with more than 2,000 traces.';\n const isDrilledEmpty = drillStack.length > 0 && pathsQuery.data !== undefined && flow.snapshot.traceCount === 0;\n const handleSignalOrderChange = (nextSignalNames: TraceSignalName[]) => {\n if (perspectiveMutation.isPending) return;\n setIsPlaying(false);\n setDetailSelection(undefined);\n setNoiseSignalName(undefined);\n const mergedSignalNames = mergeVisibleSignalOrder(signalNames, nextSignalNames);\n setPendingSignalNames(mergedSignalNames);\n perspectiveMutation.mutate(mergedSignalNames);\n };\n const filtersResolved = drillStack.length > 0 && drillInAvailable && pathsQuery.data !== undefined;\n const detailStats = filtersResolved ? findSelectionStats(flow, drillStack, detailSelection) : undefined;\n const noiseStats = filtersResolved\n ? findSelectionStats(flow, drillStack, noiseSignalName ? { kind: 'noise', signalName: noiseSignalName } : undefined)\n : undefined;\n const filterKey = serializeThemeFilters(drillStack);\n\n return (\n <main className=\"min-w-0 space-y-5 p-4 lg:p-6\">\n <div className=\"flex min-w-0 flex-wrap items-center justify-between gap-3\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-4\">\n <Tabs<SignalsViewMode>\n value={viewMode}\n defaultTab=\"flow\"\n onValueChange={handleViewModeChange}\n className=\"w-fit\"\n >\n <TabList variant=\"pill-ghost\">\n <ViewModeTab value=\"flow\" icon={<Waypoints />} label=\"Flow\" />\n <ViewModeTab value=\"compare\" icon={<ArrowLeftRight />} label=\"Compare\" />\n <ViewModeTab value=\"lifelines\" icon={<ChartNoAxesGantt />} label=\"Lifelines\" />\n </TabList>\n </Tabs>\n <TraceIntelligenceExplainer />\n </div>\n {dateRangePicker}\n </div>\n <p className=\"text-neutral3 text-xs\">{VIEW_DESCRIPTIONS[viewMode]}</p>\n {viewMode === 'compare' ? (\n <ThemeCompare\n entityId={entityId}\n entityType={entityType}\n signalNames={signalNames}\n snapshots={snapshots}\n totalSnapshots={totalSnapshots}\n onThemeSelect={openThemeDetailsAt}\n />\n ) : viewMode === 'lifelines' ? (\n <ThemeLifelines\n entityId={entityId}\n entityType={entityType}\n signalNames={signalNames}\n snapshots={snapshots}\n totalSnapshots={totalSnapshots}\n selectedIndex={selectedSnapshotIndex}\n onSnapshotSelect={selectSnapshot}\n onThemeSelect={openThemeDetailsAt}\n />\n ) : (\n <>\n <SnapshotTimeline\n snapshots={snapshots}\n selectedIndex={selectedSnapshotIndex}\n totalSnapshots={totalSnapshots}\n summary={`${drillStack.length > 0 ? (drillInAvailable ? 'Filtered · ' : 'Filters unavailable · ') : ''}${snapshotSummaryLabel(snapshot, flow)}`}\n isPlaying={isPlaying}\n onPlayingChange={handlePlayingChange}\n onSnapshotChange={selectSnapshot}\n />\n {drillStack.length > 0 ? (\n <ThemeFilterBanner\n selections={drillStack}\n filteredTraceCount={filtersResolved ? flow.snapshot.traceCount : undefined}\n totalTraceCount={currentFlow.snapshot.traceCount}\n isUnavailable={!drillInAvailable}\n onViewDetails={selection => {\n if (selection.kind === 'theme') {\n setNoiseSignalName(undefined);\n setDetailSelection(selection);\n } else {\n setDetailSelection(undefined);\n setNoiseSignalName(selection.signalName);\n }\n }}\n onRemove={signalName =>\n setDrillStack(current => current.filter(filter => filter.signalName !== signalName))\n }\n onClear={() => setDrillStack([])}\n />\n ) : null}\n {isDrilledEmpty ? (\n <section className=\"border-border1 bg-surface2 text-neutral3 rounded-lg border p-6 text-sm\">\n This theme is not present in the selected snapshot. Use the clear filter action above to return to the\n full flow.\n </section>\n ) : graphSummary.records.length === 0 ? (\n <section className=\"border-border1 bg-surface2 text-neutral3 rounded-lg border p-6 text-sm\">\n No cross-signal flow for this snapshot — its trace signals have not overlapped on shared traces yet. Pick\n another snapshot from the timeline below.\n </section>\n ) : (\n <FlowCard\n columns={graphSummary.columns}\n records={graphSummary.records}\n stages={stages}\n height={height}\n onNodeClick={handleNodeClick}\n isNodeClickable={isNodeClickable}\n drillInDisabledReason={drillInDisabledReason}\n onOrderChange={handleSignalOrderChange}\n signalOrder={pendingSignalNames ?? signalNames}\n reorderDisabled={perspectiveMutation.isPending}\n />\n )}\n {perspectiveMutation.isPending ? (\n <p className=\"text-neutral3 font-mono text-xs\" role=\"status\">\n Reloading snapshots for new trace signal perspective…\n </p>\n ) : null}\n {perspectiveMutation.isError ? (\n <p className=\"text-xs text-red-500\" role=\"alert\">\n Unable to load that trace signal perspective. Try reordering the columns again.\n </p>\n ) : null}\n </>\n )}\n <ThemeDetailPanel\n key={`${snapshot.snapshotId}:${detailSelection?.signalName ?? ''}:${detailSelection?.themeId ?? ''}:${filterKey}`}\n entityId={entityId}\n entityType={entityType}\n snapshotId={snapshot.snapshotId}\n snapshotTotal={snapshot.total}\n selection={detailSelection}\n filters={drillStack}\n filteredStats={detailStats}\n onClose={() => setDetailSelection(undefined)}\n />\n <NoiseDetailPanel\n key={`${snapshot.snapshotId}:${noiseSignalName ?? ''}:${filterKey}`}\n entityId={entityId}\n entityType={entityType}\n snapshotId={snapshot.snapshotId}\n signalName={noiseSignalName}\n filters={drillStack}\n filteredStats={noiseStats}\n onClose={() => setNoiseSignalName(undefined)}\n />\n </main>\n );\n}\n"],"names":["snapshot","SignalsEmptyState"],"mappings":"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"}
|
|
@@ -73,7 +73,7 @@ function SignalDeltaColumn({
|
|
|
73
73
|
{
|
|
74
74
|
"aria-label": `View theme details for ${delta.label}`,
|
|
75
75
|
className: "hover:border-border2 block w-full cursor-pointer rounded-lg px-2.5 py-2 text-left transition-colors hover:bg-white/[0.03]",
|
|
76
|
-
onClick: () => onThemeSelect({ signalName, themeId, label: delta.label }, detailIndexFor(delta)),
|
|
76
|
+
onClick: () => onThemeSelect({ kind: "theme", signalName, themeId, label: delta.label }, detailIndexFor(delta)),
|
|
77
77
|
type: "button",
|
|
78
78
|
children: card
|
|
79
79
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal-delta-column.cjs.js","sources":["../../../src/ee/signals/signal-delta-column.tsx"],"sourcesContent":["import { getSignalHue } from './signal-colors';\nimport { formatSignalName, SIGNAL_DESCRIPTIONS } from './signal-formatting';\nimport { computeThemeShareDeltas, themeShareSeries } from './theme-compare-data';\nimport { ThemeCompareSparkline } from './theme-compare-sparkline';\nimport type { ThemeSelection } from './theme-drilldown-data';\nimport type { ThemeFlowResponse, TraceSignalName } from './types';\nimport { nodeColor } from '@/ds/components/SankeyChart';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\n\nfunction percent(share: number) {\n return `${Math.round(share * 100)}%`;\n}\n\nfunction deltaLabel(delta: number) {\n const points = Math.round(delta * 100);\n return `${points >= 0 ? '+' : ''}${points}%`;\n}\n\nexport function SignalDeltaColumn({\n signalName,\n fromFlow,\n toFlow,\n flows,\n positions,\n fromIndex,\n toIndex,\n onThemeSelect,\n}: {\n signalName: TraceSignalName;\n fromFlow: ThemeFlowResponse;\n toFlow: ThemeFlowResponse;\n flows: Array<ThemeFlowResponse | undefined>;\n positions: number[];\n fromIndex: number;\n toIndex: number;\n onThemeSelect: (selection: ThemeSelection, snapshotIndex: number) => void;\n}) {\n const deltas = computeThemeShareDeltas(fromFlow, toFlow, signalName);\n const detailIndexFor = (delta: { toShare: number }) => (delta.toShare > 0 ? toIndex : fromIndex);\n\n return (\n <section aria-label={`${formatSignalName(signalName)} changes`} className=\"min-w-0\">\n <h3\n className=\"font-mono text-xs font-semibold tracking-widest uppercase\"\n style={{ color: nodeColor(getSignalHue(signalName)) }}\n >\n <Tooltip>\n <TooltipTrigger className=\"cursor-default uppercase\">{signalName}</TooltipTrigger>\n <TooltipContent>{SIGNAL_DESCRIPTIONS[signalName]}</TooltipContent>\n </Tooltip>\n </h3>\n <ul className=\"mt-2 space-y-1.5\">\n {deltas.length === 0 ? <li className=\"text-neutral3 text-xs\">No themes in either snapshot.</li> : null}\n {deltas.map(delta => {\n const themeId = delta.themeId;\n const card = (\n <>\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-neutral6 truncate text-xs font-medium\" title={delta.label}>\n {delta.label}\n </span>\n <span className=\"text-neutral6 shrink-0 font-mono text-xs font-semibold tabular-nums\">\n {deltaLabel(delta.delta)}\n </span>\n </div>\n <p className=\"text-neutral3 font-mono text-[11px] tabular-nums\">\n {percent(delta.fromShare)} → {percent(delta.toShare)}\n </p>\n <ThemeCompareSparkline\n series={themeShareSeries(flows, signalName, delta.label)}\n positions={positions}\n markerIndexes={[fromIndex, toIndex]}\n />\n </>\n );\n return (\n <li\n key={delta.label}\n className={`border-border1 rounded-lg border ${\n delta.delta > 0 ? 'bg-green-500/5' : delta.delta < 0 ? 'bg-red-500/5' : 'bg-surface3'\n }`}\n >\n {themeId === undefined ? (\n <div className=\"px-2.5 py-2\">{card}</div>\n ) : (\n <button\n aria-label={`View theme details for ${delta.label}`}\n className=\"hover:border-border2 block w-full cursor-pointer rounded-lg px-2.5 py-2 text-left transition-colors hover:bg-white/[0.03]\"\n onClick={()
|
|
1
|
+
{"version":3,"file":"signal-delta-column.cjs.js","sources":["../../../src/ee/signals/signal-delta-column.tsx"],"sourcesContent":["import { getSignalHue } from './signal-colors';\nimport { formatSignalName, SIGNAL_DESCRIPTIONS } from './signal-formatting';\nimport { computeThemeShareDeltas, themeShareSeries } from './theme-compare-data';\nimport { ThemeCompareSparkline } from './theme-compare-sparkline';\nimport type { ThemeSelection } from './theme-drilldown-data';\nimport type { ThemeFlowResponse, TraceSignalName } from './types';\nimport { nodeColor } from '@/ds/components/SankeyChart';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\n\nfunction percent(share: number) {\n return `${Math.round(share * 100)}%`;\n}\n\nfunction deltaLabel(delta: number) {\n const points = Math.round(delta * 100);\n return `${points >= 0 ? '+' : ''}${points}%`;\n}\n\nexport function SignalDeltaColumn({\n signalName,\n fromFlow,\n toFlow,\n flows,\n positions,\n fromIndex,\n toIndex,\n onThemeSelect,\n}: {\n signalName: TraceSignalName;\n fromFlow: ThemeFlowResponse;\n toFlow: ThemeFlowResponse;\n flows: Array<ThemeFlowResponse | undefined>;\n positions: number[];\n fromIndex: number;\n toIndex: number;\n onThemeSelect: (selection: ThemeSelection, snapshotIndex: number) => void;\n}) {\n const deltas = computeThemeShareDeltas(fromFlow, toFlow, signalName);\n const detailIndexFor = (delta: { toShare: number }) => (delta.toShare > 0 ? toIndex : fromIndex);\n\n return (\n <section aria-label={`${formatSignalName(signalName)} changes`} className=\"min-w-0\">\n <h3\n className=\"font-mono text-xs font-semibold tracking-widest uppercase\"\n style={{ color: nodeColor(getSignalHue(signalName)) }}\n >\n <Tooltip>\n <TooltipTrigger className=\"cursor-default uppercase\">{signalName}</TooltipTrigger>\n <TooltipContent>{SIGNAL_DESCRIPTIONS[signalName]}</TooltipContent>\n </Tooltip>\n </h3>\n <ul className=\"mt-2 space-y-1.5\">\n {deltas.length === 0 ? <li className=\"text-neutral3 text-xs\">No themes in either snapshot.</li> : null}\n {deltas.map(delta => {\n const themeId = delta.themeId;\n const card = (\n <>\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-neutral6 truncate text-xs font-medium\" title={delta.label}>\n {delta.label}\n </span>\n <span className=\"text-neutral6 shrink-0 font-mono text-xs font-semibold tabular-nums\">\n {deltaLabel(delta.delta)}\n </span>\n </div>\n <p className=\"text-neutral3 font-mono text-[11px] tabular-nums\">\n {percent(delta.fromShare)} → {percent(delta.toShare)}\n </p>\n <ThemeCompareSparkline\n series={themeShareSeries(flows, signalName, delta.label)}\n positions={positions}\n markerIndexes={[fromIndex, toIndex]}\n />\n </>\n );\n return (\n <li\n key={delta.label}\n className={`border-border1 rounded-lg border ${\n delta.delta > 0 ? 'bg-green-500/5' : delta.delta < 0 ? 'bg-red-500/5' : 'bg-surface3'\n }`}\n >\n {themeId === undefined ? (\n <div className=\"px-2.5 py-2\">{card}</div>\n ) : (\n <button\n aria-label={`View theme details for ${delta.label}`}\n className=\"hover:border-border2 block w-full cursor-pointer rounded-lg px-2.5 py-2 text-left transition-colors hover:bg-white/[0.03]\"\n onClick={() =>\n onThemeSelect({ kind: 'theme', signalName, themeId, label: delta.label }, detailIndexFor(delta))\n }\n type=\"button\"\n >\n {card}\n </button>\n )}\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n"],"names":["computeThemeShareDeltas","jsxs","formatSignalName","jsx","nodeColor","getSignalHue","Tooltip","TooltipTrigger","TooltipContent","SIGNAL_DESCRIPTIONS","Fragment","ThemeCompareSparkline","themeShareSeries"],"mappings":"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"}
|
|
@@ -69,7 +69,7 @@ function SignalDeltaColumn({
|
|
|
69
69
|
{
|
|
70
70
|
"aria-label": `View theme details for ${delta.label}`,
|
|
71
71
|
className: "hover:border-border2 block w-full cursor-pointer rounded-lg px-2.5 py-2 text-left transition-colors hover:bg-white/[0.03]",
|
|
72
|
-
onClick: () => onThemeSelect({ signalName, themeId, label: delta.label }, detailIndexFor(delta)),
|
|
72
|
+
onClick: () => onThemeSelect({ kind: "theme", signalName, themeId, label: delta.label }, detailIndexFor(delta)),
|
|
73
73
|
type: "button",
|
|
74
74
|
children: card
|
|
75
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal-delta-column.es.js","sources":["../../../src/ee/signals/signal-delta-column.tsx"],"sourcesContent":["import { getSignalHue } from './signal-colors';\nimport { formatSignalName, SIGNAL_DESCRIPTIONS } from './signal-formatting';\nimport { computeThemeShareDeltas, themeShareSeries } from './theme-compare-data';\nimport { ThemeCompareSparkline } from './theme-compare-sparkline';\nimport type { ThemeSelection } from './theme-drilldown-data';\nimport type { ThemeFlowResponse, TraceSignalName } from './types';\nimport { nodeColor } from '@/ds/components/SankeyChart';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\n\nfunction percent(share: number) {\n return `${Math.round(share * 100)}%`;\n}\n\nfunction deltaLabel(delta: number) {\n const points = Math.round(delta * 100);\n return `${points >= 0 ? '+' : ''}${points}%`;\n}\n\nexport function SignalDeltaColumn({\n signalName,\n fromFlow,\n toFlow,\n flows,\n positions,\n fromIndex,\n toIndex,\n onThemeSelect,\n}: {\n signalName: TraceSignalName;\n fromFlow: ThemeFlowResponse;\n toFlow: ThemeFlowResponse;\n flows: Array<ThemeFlowResponse | undefined>;\n positions: number[];\n fromIndex: number;\n toIndex: number;\n onThemeSelect: (selection: ThemeSelection, snapshotIndex: number) => void;\n}) {\n const deltas = computeThemeShareDeltas(fromFlow, toFlow, signalName);\n const detailIndexFor = (delta: { toShare: number }) => (delta.toShare > 0 ? toIndex : fromIndex);\n\n return (\n <section aria-label={`${formatSignalName(signalName)} changes`} className=\"min-w-0\">\n <h3\n className=\"font-mono text-xs font-semibold tracking-widest uppercase\"\n style={{ color: nodeColor(getSignalHue(signalName)) }}\n >\n <Tooltip>\n <TooltipTrigger className=\"cursor-default uppercase\">{signalName}</TooltipTrigger>\n <TooltipContent>{SIGNAL_DESCRIPTIONS[signalName]}</TooltipContent>\n </Tooltip>\n </h3>\n <ul className=\"mt-2 space-y-1.5\">\n {deltas.length === 0 ? <li className=\"text-neutral3 text-xs\">No themes in either snapshot.</li> : null}\n {deltas.map(delta => {\n const themeId = delta.themeId;\n const card = (\n <>\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-neutral6 truncate text-xs font-medium\" title={delta.label}>\n {delta.label}\n </span>\n <span className=\"text-neutral6 shrink-0 font-mono text-xs font-semibold tabular-nums\">\n {deltaLabel(delta.delta)}\n </span>\n </div>\n <p className=\"text-neutral3 font-mono text-[11px] tabular-nums\">\n {percent(delta.fromShare)} → {percent(delta.toShare)}\n </p>\n <ThemeCompareSparkline\n series={themeShareSeries(flows, signalName, delta.label)}\n positions={positions}\n markerIndexes={[fromIndex, toIndex]}\n />\n </>\n );\n return (\n <li\n key={delta.label}\n className={`border-border1 rounded-lg border ${\n delta.delta > 0 ? 'bg-green-500/5' : delta.delta < 0 ? 'bg-red-500/5' : 'bg-surface3'\n }`}\n >\n {themeId === undefined ? (\n <div className=\"px-2.5 py-2\">{card}</div>\n ) : (\n <button\n aria-label={`View theme details for ${delta.label}`}\n className=\"hover:border-border2 block w-full cursor-pointer rounded-lg px-2.5 py-2 text-left transition-colors hover:bg-white/[0.03]\"\n onClick={()
|
|
1
|
+
{"version":3,"file":"signal-delta-column.es.js","sources":["../../../src/ee/signals/signal-delta-column.tsx"],"sourcesContent":["import { getSignalHue } from './signal-colors';\nimport { formatSignalName, SIGNAL_DESCRIPTIONS } from './signal-formatting';\nimport { computeThemeShareDeltas, themeShareSeries } from './theme-compare-data';\nimport { ThemeCompareSparkline } from './theme-compare-sparkline';\nimport type { ThemeSelection } from './theme-drilldown-data';\nimport type { ThemeFlowResponse, TraceSignalName } from './types';\nimport { nodeColor } from '@/ds/components/SankeyChart';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\n\nfunction percent(share: number) {\n return `${Math.round(share * 100)}%`;\n}\n\nfunction deltaLabel(delta: number) {\n const points = Math.round(delta * 100);\n return `${points >= 0 ? '+' : ''}${points}%`;\n}\n\nexport function SignalDeltaColumn({\n signalName,\n fromFlow,\n toFlow,\n flows,\n positions,\n fromIndex,\n toIndex,\n onThemeSelect,\n}: {\n signalName: TraceSignalName;\n fromFlow: ThemeFlowResponse;\n toFlow: ThemeFlowResponse;\n flows: Array<ThemeFlowResponse | undefined>;\n positions: number[];\n fromIndex: number;\n toIndex: number;\n onThemeSelect: (selection: ThemeSelection, snapshotIndex: number) => void;\n}) {\n const deltas = computeThemeShareDeltas(fromFlow, toFlow, signalName);\n const detailIndexFor = (delta: { toShare: number }) => (delta.toShare > 0 ? toIndex : fromIndex);\n\n return (\n <section aria-label={`${formatSignalName(signalName)} changes`} className=\"min-w-0\">\n <h3\n className=\"font-mono text-xs font-semibold tracking-widest uppercase\"\n style={{ color: nodeColor(getSignalHue(signalName)) }}\n >\n <Tooltip>\n <TooltipTrigger className=\"cursor-default uppercase\">{signalName}</TooltipTrigger>\n <TooltipContent>{SIGNAL_DESCRIPTIONS[signalName]}</TooltipContent>\n </Tooltip>\n </h3>\n <ul className=\"mt-2 space-y-1.5\">\n {deltas.length === 0 ? <li className=\"text-neutral3 text-xs\">No themes in either snapshot.</li> : null}\n {deltas.map(delta => {\n const themeId = delta.themeId;\n const card = (\n <>\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-neutral6 truncate text-xs font-medium\" title={delta.label}>\n {delta.label}\n </span>\n <span className=\"text-neutral6 shrink-0 font-mono text-xs font-semibold tabular-nums\">\n {deltaLabel(delta.delta)}\n </span>\n </div>\n <p className=\"text-neutral3 font-mono text-[11px] tabular-nums\">\n {percent(delta.fromShare)} → {percent(delta.toShare)}\n </p>\n <ThemeCompareSparkline\n series={themeShareSeries(flows, signalName, delta.label)}\n positions={positions}\n markerIndexes={[fromIndex, toIndex]}\n />\n </>\n );\n return (\n <li\n key={delta.label}\n className={`border-border1 rounded-lg border ${\n delta.delta > 0 ? 'bg-green-500/5' : delta.delta < 0 ? 'bg-red-500/5' : 'bg-surface3'\n }`}\n >\n {themeId === undefined ? (\n <div className=\"px-2.5 py-2\">{card}</div>\n ) : (\n <button\n aria-label={`View theme details for ${delta.label}`}\n className=\"hover:border-border2 block w-full cursor-pointer rounded-lg px-2.5 py-2 text-left transition-colors hover:bg-white/[0.03]\"\n onClick={() =>\n onThemeSelect({ kind: 'theme', signalName, themeId, label: delta.label }, detailIndexFor(delta))\n }\n type=\"button\"\n >\n {card}\n </button>\n )}\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -25,9 +25,12 @@ function ThemeDetailPanel({
|
|
|
25
25
|
snapshotId,
|
|
26
26
|
snapshotTotal,
|
|
27
27
|
selection,
|
|
28
|
+
filters = [],
|
|
29
|
+
filteredStats,
|
|
28
30
|
onClose
|
|
29
31
|
}) {
|
|
30
|
-
const
|
|
32
|
+
const filterKey = filters.map((filter) => `${filter.signalName}:${filter.kind === "theme" ? filter.themeId : "noise"}`).join(",");
|
|
33
|
+
const examplesContextKey = `${snapshotId}:${selection?.signalName ?? ""}:${selection?.themeId ?? ""}:${filterKey}`;
|
|
31
34
|
const [examplesPage, setExamplesPage] = React.useState(() => ({ contextKey: examplesContextKey, offset: 0 }));
|
|
32
35
|
const examplesOffset = examplesPage.contextKey === examplesContextKey ? examplesPage.offset : 0;
|
|
33
36
|
const [insightTraceId, setInsightTraceId] = React.useState();
|
|
@@ -45,7 +48,8 @@ function ThemeDetailPanel({
|
|
|
45
48
|
snapshotId,
|
|
46
49
|
selection?.themeId,
|
|
47
50
|
ee_signals_examplesPager.EXAMPLES_PAGE_SIZE,
|
|
48
|
-
examplesOffset
|
|
51
|
+
examplesOffset,
|
|
52
|
+
filters
|
|
49
53
|
);
|
|
50
54
|
const historyQuery = ee_signals_hooks_useThemeHistory.useThemeHistory(
|
|
51
55
|
entityId,
|
|
@@ -105,7 +109,10 @@ function ThemeDetailPanel({
|
|
|
105
109
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-labelledby": "theme-summary-heading", children: [
|
|
106
110
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: "theme-summary-heading", className: "text-neutral3 font-mono text-xs tracking-wider uppercase", children: "Summary" }),
|
|
107
111
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-neutral5 mt-3 text-sm", children: detailQuery.data.theme.description ?? "No description available." }),
|
|
108
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-neutral5 mt-3 font-mono text-sm tabular-nums", children: ee_signals_signalFormatting.shareSentence(
|
|
112
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-neutral5 mt-3 font-mono text-sm tabular-nums", children: ee_signals_signalFormatting.shareSentence(
|
|
113
|
+
filteredStats?.traceCount ?? detailQuery.data.theme.traceCount,
|
|
114
|
+
filteredStats?.stageShare ?? detailQuery.data.theme.coverage
|
|
115
|
+
) })
|
|
109
116
|
] }),
|
|
110
117
|
/* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-labelledby": "theme-examples-heading", children: [
|
|
111
118
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -132,7 +139,7 @@ function ThemeDetailPanel({
|
|
|
132
139
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
133
140
|
ee_signals_examplesPager.ExamplesPager,
|
|
134
141
|
{
|
|
135
|
-
traceCount: detailQuery.data.theme.traceCount,
|
|
142
|
+
traceCount: filteredStats?.traceCount ?? detailQuery.data.theme.traceCount,
|
|
136
143
|
offset: examplesOffset,
|
|
137
144
|
onOffsetChange: (offset) => setExamplesPage({ contextKey: examplesContextKey, offset })
|
|
138
145
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-detail-panel.cjs.js","sources":["../../../src/ee/signals/theme-detail-panel.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { EXAMPLES_PAGE_SIZE, ExamplesPager } from './examples-pager';\nimport { useThemeDetail, useThemeExamples, useThemeHistory } from './hooks';\nimport { getSignalHue } from './signal-colors';\nimport { formatSnapshotDate, shareSentence, SIGNAL_DESCRIPTIONS } from './signal-formatting';\nimport type { ThemeSelection } from './theme-drilldown-data';\nimport { chronologicalHistoryPoints, themeTrendDirection } from './theme-trend';\nimport { ThemeTrendChart } from './theme-trend-chart';\nimport { TraceInsightView } from './trace-insight-view';\nimport {\n Drawer,\n DrawerBody,\n DrawerContent,\n DrawerDescription,\n DrawerHeader,\n DrawerTitle,\n} from '@/ds/components/Drawer';\nimport { nodeColor } from '@/ds/components/SankeyChart';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\n\ninterface ThemeDetailPanelProps {\n entityId: string;\n entityType: string;\n snapshotId: string;\n snapshotTotal: number;\n selection: ThemeSelection | undefined;\n onClose: () => void;\n}\n\nexport function ThemeDetailPanel({\n entityId,\n entityType,\n snapshotId,\n snapshotTotal,\n selection,\n onClose,\n}: ThemeDetailPanelProps) {\n const examplesContextKey = `${snapshotId}:${selection?.signalName ?? ''}:${selection?.themeId ?? ''}`;\n const [examplesPage, setExamplesPage] = useState(() => ({ contextKey: examplesContextKey, offset: 0 }));\n const examplesOffset = examplesPage.contextKey === examplesContextKey ? examplesPage.offset : 0;\n const [insightTraceId, setInsightTraceId] = useState<string>();\n const detailQuery = useThemeDetail(\n entityId,\n entityType,\n selection?.signalName ?? 'goal',\n snapshotId,\n selection?.themeId,\n );\n const examplesQuery = useThemeExamples(\n entityId,\n entityType,\n selection?.signalName ?? 'goal',\n snapshotId,\n selection?.themeId,\n EXAMPLES_PAGE_SIZE,\n examplesOffset,\n );\n const historyQuery = useThemeHistory(\n entityId,\n entityType,\n selection?.signalName ?? 'goal',\n snapshotTotal > 1 ? selection?.themeId : undefined,\n );\n const title = detailQuery.data?.theme?.label ?? selection?.label ?? 'Theme details';\n const signalName = selection?.signalName;\n const historyPoints = historyQuery.data ? chronologicalHistoryPoints(historyQuery.data.points) : [];\n const oldestHistoryPoint = historyPoints[0];\n\n return (\n <Drawer\n onOpenChange={open => {\n if (!open) {\n setExamplesPage({ contextKey: '', offset: 0 });\n setInsightTraceId(undefined);\n onClose();\n }\n }}\n open={selection !== undefined}\n overlay=\"none\"\n side=\"right\"\n variant=\"floating\"\n >\n <DrawerContent>\n <DrawerHeader className=\"border-border1 border-b\">\n {signalName !== undefined && (\n <span\n className=\"font-mono text-xs font-semibold tracking-widest\"\n style={{ color: nodeColor(getSignalHue(signalName)) }}\n >\n <Tooltip>\n <TooltipTrigger className=\"cursor-default uppercase\">{signalName}</TooltipTrigger>\n <TooltipContent>{SIGNAL_DESCRIPTIONS[signalName]}</TooltipContent>\n </Tooltip>\n </span>\n )}\n <DrawerTitle>{title}</DrawerTitle>\n <DrawerDescription className=\"sr-only\">\n Details for the {signalName ?? 'selected'} theme {title}\n </DrawerDescription>\n </DrawerHeader>\n <DrawerBody className=\"grid content-start gap-6 overflow-y-auto p-6\">\n {insightTraceId !== undefined && (\n <TraceInsightView traceId={insightTraceId} onBack={() => setInsightTraceId(undefined)} />\n )}\n {insightTraceId === undefined && (\n <>\n {detailQuery.isPending && <p className=\"text-neutral3 text-sm\">Loading theme details…</p>}\n {detailQuery.isError && <p className=\"text-sm text-red-500\">Unable to load theme details.</p>}\n {detailQuery.data && !detailQuery.data.theme && (\n <section>\n <h2 className=\"text-neutral6 text-sm font-semibold\">Not present in this snapshot</h2>\n <p className=\"text-neutral3 mt-2 text-sm\">This theme has no data in the selected snapshot.</p>\n </section>\n )}\n {detailQuery.data?.theme && (\n <>\n <section aria-labelledby=\"theme-summary-heading\">\n <h2 id=\"theme-summary-heading\" className=\"text-neutral3 font-mono text-xs tracking-wider uppercase\">\n Summary\n </h2>\n <p className=\"text-neutral5 mt-3 text-sm\">\n {detailQuery.data.theme.description ?? 'No description available.'}\n </p>\n <p className=\"text-neutral5 mt-3 font-mono text-sm tabular-nums\">\n {shareSentence(detailQuery.data.theme.traceCount, detailQuery.data.theme.coverage)}\n </p>\n </section>\n\n <section aria-labelledby=\"theme-examples-heading\">\n <h2\n id=\"theme-examples-heading\"\n className=\"text-neutral3 font-mono text-xs tracking-wider uppercase\"\n >\n Examples\n </h2>\n {examplesQuery.isPending && <p className=\"text-neutral3 mt-3 text-sm\">Loading examples…</p>}\n {examplesQuery.isError && <p className=\"mt-3 text-sm text-red-500\">Unable to load examples.</p>}\n {examplesQuery.data && (\n <>\n {examplesQuery.data.examples.length === 0 ? (\n <p className=\"text-neutral3 mt-3 text-sm\">No examples in this snapshot.</p>\n ) : (\n <ul className=\"mt-3 space-y-3\">\n {examplesQuery.data.examples.map(example => (\n <li key={example.traceId}>\n <button\n type=\"button\"\n aria-label={`View trace insight for ${example.signalText}`}\n className=\"border-border1 bg-surface3 text-neutral5 hover:bg-surface5 w-full cursor-pointer rounded-md border p-3 text-left text-sm\"\n onClick={() => setInsightTraceId(example.traceId)}\n >\n {example.signalText}\n </button>\n </li>\n ))}\n </ul>\n )}\n <ExamplesPager\n traceCount={detailQuery.data.theme.traceCount}\n offset={examplesOffset}\n onOffsetChange={offset => setExamplesPage({ contextKey: examplesContextKey, offset })}\n />\n </>\n )}\n </section>\n\n {snapshotTotal > 1 && (\n <section aria-labelledby=\"theme-trend-heading\">\n <h2 id=\"theme-trend-heading\" className=\"text-neutral3 font-mono text-xs tracking-wider uppercase\">\n Trend\n </h2>\n {historyQuery.isPending && <p className=\"text-neutral3 mt-3 text-sm\">Loading trend…</p>}\n {historyQuery.isError && <p className=\"mt-3 text-sm text-red-500\">Unable to load the trend.</p>}\n {oldestHistoryPoint !== undefined && (\n <>\n <p className=\"text-neutral5 mt-3 text-sm\">\n {/* A nextCursor means older points exist beyond the fetched window,\n so the oldest loaded point is a lower bound, not the true origin. */}\n {historyQuery.data?.nextCursor\n ? `Active since at least ${formatSnapshotDate(oldestHistoryPoint.startedAt)} · in ${historyPoints.length}+ snapshots`\n : `First seen ${formatSnapshotDate(oldestHistoryPoint.startedAt)} · in ${historyPoints.length} ${historyPoints.length === 1 ? 'snapshot' : 'snapshots'}`}{' '}\n · {themeTrendDirection(historyPoints)}\n </p>\n {historyPoints.length >= 2 && (\n <ThemeTrendChart\n points={historyPoints}\n color={nodeColor(getSignalHue(signalName ?? 'goal'))}\n />\n )}\n </>\n )}\n </section>\n )}\n </>\n )}\n </>\n )}\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n );\n}\n"],"names":["useState","useThemeDetail","useThemeExamples","EXAMPLES_PAGE_SIZE","useThemeHistory","chronologicalHistoryPoints","jsx","Drawer","DrawerContent","jsxs","DrawerHeader","nodeColor","getSignalHue","Tooltip","TooltipTrigger","TooltipContent","SIGNAL_DESCRIPTIONS","DrawerTitle","DrawerDescription","DrawerBody","TraceInsightView","Fragment","shareSentence","ExamplesPager","formatSnapshotDate","themeTrendDirection","ThemeTrendChart"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"theme-detail-panel.cjs.js","sources":["../../../src/ee/signals/theme-detail-panel.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { EXAMPLES_PAGE_SIZE, ExamplesPager } from './examples-pager';\nimport { useThemeDetail, useThemeExamples, useThemeHistory } from './hooks';\nimport { getSignalHue } from './signal-colors';\nimport { formatSnapshotDate, shareSentence, SIGNAL_DESCRIPTIONS } from './signal-formatting';\nimport type { SelectedTheme, ThemeSelection, ThemeSelectionStats } from './theme-drilldown-data';\nimport { chronologicalHistoryPoints, themeTrendDirection } from './theme-trend';\nimport { ThemeTrendChart } from './theme-trend-chart';\nimport { TraceInsightView } from './trace-insight-view';\nimport {\n Drawer,\n DrawerBody,\n DrawerContent,\n DrawerDescription,\n DrawerHeader,\n DrawerTitle,\n} from '@/ds/components/Drawer';\nimport { nodeColor } from '@/ds/components/SankeyChart';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\n\ninterface ThemeDetailPanelProps {\n entityId: string;\n entityType: string;\n snapshotId: string;\n snapshotTotal: number;\n selection: SelectedTheme | undefined;\n filters?: ThemeSelection[];\n filteredStats?: ThemeSelectionStats;\n onClose: () => void;\n}\n\nexport function ThemeDetailPanel({\n entityId,\n entityType,\n snapshotId,\n snapshotTotal,\n selection,\n filters = [],\n filteredStats,\n onClose,\n}: ThemeDetailPanelProps) {\n const filterKey = filters\n .map(filter => `${filter.signalName}:${filter.kind === 'theme' ? filter.themeId : 'noise'}`)\n .join(',');\n const examplesContextKey = `${snapshotId}:${selection?.signalName ?? ''}:${selection?.themeId ?? ''}:${filterKey}`;\n const [examplesPage, setExamplesPage] = useState(() => ({ contextKey: examplesContextKey, offset: 0 }));\n const examplesOffset = examplesPage.contextKey === examplesContextKey ? examplesPage.offset : 0;\n const [insightTraceId, setInsightTraceId] = useState<string>();\n const detailQuery = useThemeDetail(\n entityId,\n entityType,\n selection?.signalName ?? 'goal',\n snapshotId,\n selection?.themeId,\n );\n const examplesQuery = useThemeExamples(\n entityId,\n entityType,\n selection?.signalName ?? 'goal',\n snapshotId,\n selection?.themeId,\n EXAMPLES_PAGE_SIZE,\n examplesOffset,\n filters,\n );\n const historyQuery = useThemeHistory(\n entityId,\n entityType,\n selection?.signalName ?? 'goal',\n snapshotTotal > 1 ? selection?.themeId : undefined,\n );\n const title = detailQuery.data?.theme?.label ?? selection?.label ?? 'Theme details';\n const signalName = selection?.signalName;\n const historyPoints = historyQuery.data ? chronologicalHistoryPoints(historyQuery.data.points) : [];\n const oldestHistoryPoint = historyPoints[0];\n\n return (\n <Drawer\n onOpenChange={open => {\n if (!open) {\n setExamplesPage({ contextKey: '', offset: 0 });\n setInsightTraceId(undefined);\n onClose();\n }\n }}\n open={selection !== undefined}\n overlay=\"none\"\n side=\"right\"\n variant=\"floating\"\n >\n <DrawerContent>\n <DrawerHeader className=\"border-border1 border-b\">\n {signalName !== undefined && (\n <span\n className=\"font-mono text-xs font-semibold tracking-widest\"\n style={{ color: nodeColor(getSignalHue(signalName)) }}\n >\n <Tooltip>\n <TooltipTrigger className=\"cursor-default uppercase\">{signalName}</TooltipTrigger>\n <TooltipContent>{SIGNAL_DESCRIPTIONS[signalName]}</TooltipContent>\n </Tooltip>\n </span>\n )}\n <DrawerTitle>{title}</DrawerTitle>\n <DrawerDescription className=\"sr-only\">\n Details for the {signalName ?? 'selected'} theme {title}\n </DrawerDescription>\n </DrawerHeader>\n <DrawerBody className=\"grid content-start gap-6 overflow-y-auto p-6\">\n {insightTraceId !== undefined && (\n <TraceInsightView traceId={insightTraceId} onBack={() => setInsightTraceId(undefined)} />\n )}\n {insightTraceId === undefined && (\n <>\n {detailQuery.isPending && <p className=\"text-neutral3 text-sm\">Loading theme details…</p>}\n {detailQuery.isError && <p className=\"text-sm text-red-500\">Unable to load theme details.</p>}\n {detailQuery.data && !detailQuery.data.theme && (\n <section>\n <h2 className=\"text-neutral6 text-sm font-semibold\">Not present in this snapshot</h2>\n <p className=\"text-neutral3 mt-2 text-sm\">This theme has no data in the selected snapshot.</p>\n </section>\n )}\n {detailQuery.data?.theme && (\n <>\n <section aria-labelledby=\"theme-summary-heading\">\n <h2 id=\"theme-summary-heading\" className=\"text-neutral3 font-mono text-xs tracking-wider uppercase\">\n Summary\n </h2>\n <p className=\"text-neutral5 mt-3 text-sm\">\n {detailQuery.data.theme.description ?? 'No description available.'}\n </p>\n <p className=\"text-neutral5 mt-3 font-mono text-sm tabular-nums\">\n {shareSentence(\n filteredStats?.traceCount ?? detailQuery.data.theme.traceCount,\n filteredStats?.stageShare ?? detailQuery.data.theme.coverage,\n )}\n </p>\n </section>\n\n <section aria-labelledby=\"theme-examples-heading\">\n <h2\n id=\"theme-examples-heading\"\n className=\"text-neutral3 font-mono text-xs tracking-wider uppercase\"\n >\n Examples\n </h2>\n {examplesQuery.isPending && <p className=\"text-neutral3 mt-3 text-sm\">Loading examples…</p>}\n {examplesQuery.isError && <p className=\"mt-3 text-sm text-red-500\">Unable to load examples.</p>}\n {examplesQuery.data && (\n <>\n {examplesQuery.data.examples.length === 0 ? (\n <p className=\"text-neutral3 mt-3 text-sm\">No examples in this snapshot.</p>\n ) : (\n <ul className=\"mt-3 space-y-3\">\n {examplesQuery.data.examples.map(example => (\n <li key={example.traceId}>\n <button\n type=\"button\"\n aria-label={`View trace insight for ${example.signalText}`}\n className=\"border-border1 bg-surface3 text-neutral5 hover:bg-surface5 w-full cursor-pointer rounded-md border p-3 text-left text-sm\"\n onClick={() => setInsightTraceId(example.traceId)}\n >\n {example.signalText}\n </button>\n </li>\n ))}\n </ul>\n )}\n <ExamplesPager\n traceCount={filteredStats?.traceCount ?? detailQuery.data.theme.traceCount}\n offset={examplesOffset}\n onOffsetChange={offset => setExamplesPage({ contextKey: examplesContextKey, offset })}\n />\n </>\n )}\n </section>\n\n {snapshotTotal > 1 && (\n <section aria-labelledby=\"theme-trend-heading\">\n <h2 id=\"theme-trend-heading\" className=\"text-neutral3 font-mono text-xs tracking-wider uppercase\">\n Trend\n </h2>\n {historyQuery.isPending && <p className=\"text-neutral3 mt-3 text-sm\">Loading trend…</p>}\n {historyQuery.isError && <p className=\"mt-3 text-sm text-red-500\">Unable to load the trend.</p>}\n {oldestHistoryPoint !== undefined && (\n <>\n <p className=\"text-neutral5 mt-3 text-sm\">\n {/* A nextCursor means older points exist beyond the fetched window,\n so the oldest loaded point is a lower bound, not the true origin. */}\n {historyQuery.data?.nextCursor\n ? `Active since at least ${formatSnapshotDate(oldestHistoryPoint.startedAt)} · in ${historyPoints.length}+ snapshots`\n : `First seen ${formatSnapshotDate(oldestHistoryPoint.startedAt)} · in ${historyPoints.length} ${historyPoints.length === 1 ? 'snapshot' : 'snapshots'}`}{' '}\n · {themeTrendDirection(historyPoints)}\n </p>\n {historyPoints.length >= 2 && (\n <ThemeTrendChart\n points={historyPoints}\n color={nodeColor(getSignalHue(signalName ?? 'goal'))}\n />\n )}\n </>\n )}\n </section>\n )}\n </>\n )}\n </>\n )}\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n );\n}\n"],"names":["useState","useThemeDetail","useThemeExamples","EXAMPLES_PAGE_SIZE","useThemeHistory","chronologicalHistoryPoints","jsx","Drawer","DrawerContent","jsxs","DrawerHeader","nodeColor","getSignalHue","Tooltip","TooltipTrigger","TooltipContent","SIGNAL_DESCRIPTIONS","DrawerTitle","DrawerDescription","DrawerBody","TraceInsightView","Fragment","shareSentence","ExamplesPager","formatSnapshotDate","themeTrendDirection","ThemeTrendChart"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAgCO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,QAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAU,EAAC;AAAA,EACX,aAAA;AAAA,EACA;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,YAAY,OAAA,CACf,GAAA,CAAI,CAAA,MAAA,KAAU,CAAA,EAAG,OAAO,UAAU,CAAA,CAAA,EAAI,MAAA,CAAO,IAAA,KAAS,UAAU,MAAA,CAAO,OAAA,GAAU,OAAO,CAAA,CAAE,CAAA,CAC1F,KAAK,GAAG,CAAA;AACX,EAAA,MAAM,kBAAA,GAAqB,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,SAAA,EAAW,UAAA,IAAc,EAAE,CAAA,CAAA,EAAI,SAAA,EAAW,OAAA,IAAW,EAAE,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAChH,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIA,cAAA,CAAS,OAAO,EAAE,UAAA,EAAY,kBAAA,EAAoB,MAAA,EAAQ,CAAA,EAAE,CAAE,CAAA;AACtG,EAAA,MAAM,cAAA,GAAiB,YAAA,CAAa,UAAA,KAAe,kBAAA,GAAqB,aAAa,MAAA,GAAS,CAAA;AAC9F,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,cAAA,EAAiB;AAC7D,EAAA,MAAM,WAAA,GAAcC,8CAAA;AAAA,IAClB,QAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAW,UAAA,IAAc,MAAA;AAAA,IACzB,UAAA;AAAA,IACA,SAAA,EAAW;AAAA,GACb;AACA,EAAA,MAAM,aAAA,GAAgBC,kDAAA;AAAA,IACpB,QAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAW,UAAA,IAAc,MAAA;AAAA,IACzB,UAAA;AAAA,IACA,SAAA,EAAW,OAAA;AAAA,IACXC,2CAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,YAAA,GAAeC,gDAAA;AAAA,IACnB,QAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAW,UAAA,IAAc,MAAA;AAAA,IACzB,aAAA,GAAgB,CAAA,GAAI,SAAA,EAAW,OAAA,GAAU;AAAA,GAC3C;AACA,EAAA,MAAM,QAAQ,WAAA,CAAY,IAAA,EAAM,KAAA,EAAO,KAAA,IAAS,WAAW,KAAA,IAAS,eAAA;AACpE,EAAA,MAAM,aAAa,SAAA,EAAW,UAAA;AAC9B,EAAA,MAAM,aAAA,GAAgB,aAAa,IAAA,GAAOC,gDAAA,CAA2B,aAAa,IAAA,CAAK,MAAM,IAAI,EAAC;AAClG,EAAA,MAAM,kBAAA,GAAqB,cAAc,CAAC,CAAA;AAE1C,EAAA,uBACEC,cAAA;AAAA,IAACC,aAAA;AAAA,IAAA;AAAA,MACC,cAAc,CAAA,IAAA,KAAQ;AACpB,QAAA,IAAI,CAAC,IAAA,EAAM;AACT,UAAA,eAAA,CAAgB,EAAE,UAAA,EAAY,EAAA,EAAI,MAAA,EAAQ,GAAG,CAAA;AAC7C,UAAA,iBAAA,CAAkB,MAAS,CAAA;AAC3B,UAAA,OAAA,EAAQ;AAAA,QACV;AAAA,MACF,CAAA;AAAA,MACA,MAAM,SAAA,KAAc,MAAA;AAAA,MACpB,OAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAK,OAAA;AAAA,MACL,OAAA,EAAQ,UAAA;AAAA,MAER,0CAACC,oBAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAAC,eAAA,CAACC,mBAAA,EAAA,EAAa,WAAU,yBAAA,EACrB,QAAA,EAAA;AAAA,UAAA,UAAA,KAAe,MAAA,oBACdJ,cAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,iDAAA;AAAA,cACV,OAAO,EAAE,KAAA,EAAOK,sBAAUC,oCAAA,CAAa,UAAU,CAAC,CAAA,EAAE;AAAA,cAEpD,0CAACC,eAAA,EAAA,EACC,QAAA,EAAA;AAAA,gCAAAP,cAAA,CAACQ,sBAAA,EAAA,EAAe,SAAA,EAAU,0BAAA,EAA4B,QAAA,EAAA,UAAA,EAAW,CAAA;AAAA,gCACjER,cAAA,CAACS,sBAAA,EAAA,EAAgB,QAAA,EAAAC,+CAAA,CAAoB,UAAU,CAAA,EAAE;AAAA,eAAA,EACnD;AAAA;AAAA,WACF;AAAA,0BAEFV,cAAA,CAACW,sBAAa,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,0BACpBR,eAAA,CAACS,wBAAA,EAAA,EAAkB,SAAA,EAAU,SAAA,EAAU,QAAA,EAAA;AAAA,YAAA,kBAAA;AAAA,YACpB,UAAA,IAAc,UAAA;AAAA,YAAW,SAAA;AAAA,YAAQ;AAAA,WAAA,EACpD;AAAA,SAAA,EACF,CAAA;AAAA,wBACAT,eAAA,CAACU,iBAAA,EAAA,EAAW,SAAA,EAAU,8CAAA,EACnB,QAAA,EAAA;AAAA,UAAA,cAAA,KAAmB,MAAA,mCACjBC,4CAAA,EAAA,EAAiB,OAAA,EAAS,gBAAgB,MAAA,EAAQ,MAAM,iBAAA,CAAkB,MAAS,CAAA,EAAG,CAAA;AAAA,UAExF,cAAA,KAAmB,0BAClBX,eAAA,CAAAY,mBAAA,EAAA,EACG,QAAA,EAAA;AAAA,YAAA,WAAA,CAAY,SAAA,oBAAaf,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,yBAAwB,QAAA,EAAA,wBAAA,EAAsB,CAAA;AAAA,YACpF,YAAY,OAAA,oBAAWA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,wBAAuB,QAAA,EAAA,+BAAA,EAA6B,CAAA;AAAA,YACxF,YAAY,IAAA,IAAQ,CAAC,YAAY,IAAA,CAAK,KAAA,oCACpC,SAAA,EAAA,EACC,QAAA,EAAA;AAAA,8BAAAA,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,qCAAA,EAAsC,QAAA,EAAA,8BAAA,EAA4B,CAAA;AAAA,8BAChFA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4BAAA,EAA6B,QAAA,EAAA,kDAAA,EAAgD;AAAA,aAAA,EAC5F,CAAA;AAAA,YAED,WAAA,CAAY,IAAA,EAAM,KAAA,oBACjBG,eAAA,CAAAY,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,8BAAAZ,eAAA,CAAC,SAAA,EAAA,EAAQ,mBAAgB,uBAAA,EACvB,QAAA,EAAA;AAAA,gCAAAH,cAAA,CAAC,IAAA,EAAA,EAAG,EAAA,EAAG,uBAAA,EAAwB,SAAA,EAAU,4DAA2D,QAAA,EAAA,SAAA,EAEpG,CAAA;AAAA,gCACAA,cAAA,CAAC,OAAE,SAAA,EAAU,4BAAA,EACV,sBAAY,IAAA,CAAK,KAAA,CAAM,eAAe,2BAAA,EACzC,CAAA;AAAA,gCACAA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,mDAAA,EACV,QAAA,EAAAgB,yCAAA;AAAA,kBACC,aAAA,EAAe,UAAA,IAAc,WAAA,CAAY,IAAA,CAAK,KAAA,CAAM,UAAA;AAAA,kBACpD,aAAA,EAAe,UAAA,IAAc,WAAA,CAAY,IAAA,CAAK,KAAA,CAAM;AAAA,iBACtD,EACF;AAAA,eAAA,EACF,CAAA;AAAA,8BAEAb,eAAA,CAAC,SAAA,EAAA,EAAQ,iBAAA,EAAgB,wBAAA,EACvB,QAAA,EAAA;AAAA,gCAAAH,cAAA;AAAA,kBAAC,IAAA;AAAA,kBAAA;AAAA,oBACC,EAAA,EAAG,wBAAA;AAAA,oBACH,SAAA,EAAU,0DAAA;AAAA,oBACX,QAAA,EAAA;AAAA;AAAA,iBAED;AAAA,gBACC,cAAc,SAAA,oBAAaA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,8BAA6B,QAAA,EAAA,mBAAA,EAAiB,CAAA;AAAA,gBACtF,cAAc,OAAA,oBAAWA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,6BAA4B,QAAA,EAAA,0BAAA,EAAwB,CAAA;AAAA,gBAC1F,aAAA,CAAc,wBACbG,eAAA,CAAAY,mBAAA,EAAA,EACG,QAAA,EAAA;AAAA,kBAAA,aAAA,CAAc,IAAA,CAAK,SAAS,MAAA,KAAW,CAAA,kCACrC,GAAA,EAAA,EAAE,SAAA,EAAU,8BAA6B,QAAA,EAAA,+BAAA,EAA6B,CAAA,kCAEtE,IAAA,EAAA,EAAG,SAAA,EAAU,kBACX,QAAA,EAAA,aAAA,CAAc,IAAA,CAAK,SAAS,GAAA,CAAI,CAAA,OAAA,oCAC9B,IAAA,EAAA,EACC,QAAA,kBAAAf,cAAA;AAAA,oBAAC,QAAA;AAAA,oBAAA;AAAA,sBACC,IAAA,EAAK,QAAA;AAAA,sBACL,YAAA,EAAY,CAAA,uBAAA,EAA0B,OAAA,CAAQ,UAAU,CAAA,CAAA;AAAA,sBACxD,SAAA,EAAU,0HAAA;AAAA,sBACV,OAAA,EAAS,MAAM,iBAAA,CAAkB,OAAA,CAAQ,OAAO,CAAA;AAAA,sBAE/C,QAAA,EAAA,OAAA,CAAQ;AAAA;AAAA,mBACX,EAAA,EARO,OAAA,CAAQ,OASjB,CACD,CAAA,EACH,CAAA;AAAA,kCAEFA,cAAA;AAAA,oBAACiB,sCAAA;AAAA,oBAAA;AAAA,sBACC,UAAA,EAAY,aAAA,EAAe,UAAA,IAAc,WAAA,CAAY,KAAK,KAAA,CAAM,UAAA;AAAA,sBAChE,MAAA,EAAQ,cAAA;AAAA,sBACR,gBAAgB,CAAA,MAAA,KAAU,eAAA,CAAgB,EAAE,UAAA,EAAY,kBAAA,EAAoB,QAAQ;AAAA;AAAA;AACtF,iBAAA,EACF;AAAA,eAAA,EAEJ,CAAA;AAAA,cAEC,aAAA,GAAgB,CAAA,oBACfd,eAAA,CAAC,SAAA,EAAA,EAAQ,mBAAgB,qBAAA,EACvB,QAAA,EAAA;AAAA,gCAAAH,cAAA,CAAC,IAAA,EAAA,EAAG,EAAA,EAAG,qBAAA,EAAsB,SAAA,EAAU,4DAA2D,QAAA,EAAA,OAAA,EAElG,CAAA;AAAA,gBACC,aAAa,SAAA,oBAAaA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,8BAA6B,QAAA,EAAA,gBAAA,EAAc,CAAA;AAAA,gBAClF,aAAa,OAAA,oBAAWA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,6BAA4B,QAAA,EAAA,2BAAA,EAAyB,CAAA;AAAA,gBAC1F,kBAAA,KAAuB,0BACtBG,eAAA,CAAAY,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,kCAAAZ,eAAA,CAAC,GAAA,EAAA,EAAE,WAAU,4BAAA,EAGV,QAAA,EAAA;AAAA,oBAAA,YAAA,CAAa,IAAA,EAAM,UAAA,GAChB,CAAA,sBAAA,EAAyBe,8CAAA,CAAmB,kBAAA,CAAmB,SAAS,CAAC,CAAA,MAAA,EAAS,aAAA,CAAc,MAAM,CAAA,WAAA,CAAA,GACtG,CAAA,WAAA,EAAcA,+CAAmB,kBAAA,CAAmB,SAAS,CAAC,CAAA,MAAA,EAAS,aAAA,CAAc,MAAM,IAAI,aAAA,CAAc,MAAA,KAAW,CAAA,GAAI,UAAA,GAAa,WAAW,CAAA,CAAA;AAAA,oBAAI,GAAA;AAAA,oBAAI,IAAA;AAAA,oBAC7JC,0CAAoB,aAAa;AAAA,mBAAA,EACtC,CAAA;AAAA,kBACC,aAAA,CAAc,UAAU,CAAA,oBACvBnB,cAAA;AAAA,oBAACoB,0CAAA;AAAA,oBAAA;AAAA,sBACC,MAAA,EAAQ,aAAA;AAAA,sBACR,KAAA,EAAOf,qBAAA,CAAUC,oCAAA,CAAa,UAAA,IAAc,MAAM,CAAC;AAAA;AAAA;AACrD,iBAAA,EAEJ;AAAA,eAAA,EAEJ;AAAA,aAAA,EAEJ;AAAA,WAAA,EAEJ;AAAA,SAAA,EAEJ;AAAA,OAAA,EACF;AAAA;AAAA,GACF;AAEJ;;;;"}
|