footprint-explainable-ui 0.3.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -3
- package/dist/adapters/fromRuntimeSnapshot.d.ts +52 -0
- package/dist/adapters/fromRuntimeSnapshot.d.ts.map +1 -0
- package/dist/adapters/fromRuntimeSnapshot.js +97 -0
- package/dist/adapters/fromRuntimeSnapshot.js.map +1 -0
- package/dist/components/ExplainableShell/ExplainableShell.d.ts +26 -0
- package/dist/components/ExplainableShell/ExplainableShell.d.ts.map +1 -0
- package/dist/components/ExplainableShell/ExplainableShell.js +94 -0
- package/dist/components/ExplainableShell/ExplainableShell.js.map +1 -0
- package/dist/components/ExplainableShell/index.d.ts +3 -0
- package/dist/components/ExplainableShell/index.d.ts.map +1 -0
- package/dist/components/ExplainableShell/index.js +2 -0
- package/dist/components/ExplainableShell/index.js.map +1 -0
- package/dist/components/FlowchartView/FlowchartView.d.ts +20 -0
- package/dist/components/FlowchartView/FlowchartView.d.ts.map +1 -0
- package/dist/components/FlowchartView/FlowchartView.js +80 -0
- package/dist/components/FlowchartView/FlowchartView.js.map +1 -0
- package/dist/components/FlowchartView/SubflowBreadcrumb.d.ts +11 -0
- package/dist/components/FlowchartView/SubflowBreadcrumb.d.ts.map +1 -0
- package/dist/components/FlowchartView/SubflowBreadcrumb.js +49 -0
- package/dist/components/FlowchartView/SubflowBreadcrumb.js.map +1 -0
- package/dist/components/FlowchartView/SubflowTree.d.ts +36 -0
- package/dist/components/FlowchartView/SubflowTree.d.ts.map +1 -0
- package/dist/components/FlowchartView/SubflowTree.js +143 -0
- package/dist/components/FlowchartView/SubflowTree.js.map +1 -0
- package/dist/components/FlowchartView/TracedFlowchartView.d.ts +20 -0
- package/dist/components/FlowchartView/TracedFlowchartView.d.ts.map +1 -0
- package/dist/components/FlowchartView/TracedFlowchartView.js +101 -0
- package/dist/components/FlowchartView/TracedFlowchartView.js.map +1 -0
- package/dist/components/FlowchartView/index.d.ts +11 -0
- package/dist/components/FlowchartView/index.d.ts.map +1 -0
- package/dist/components/FlowchartView/index.js +6 -0
- package/dist/components/FlowchartView/index.js.map +1 -0
- package/dist/components/FlowchartView/specToReactFlow.d.ts +56 -0
- package/dist/components/FlowchartView/specToReactFlow.d.ts.map +1 -0
- package/dist/components/FlowchartView/specToReactFlow.js +202 -0
- package/dist/components/FlowchartView/specToReactFlow.js.map +1 -0
- package/dist/components/FlowchartView/useSubflowNavigation.d.ts +35 -0
- package/dist/components/FlowchartView/useSubflowNavigation.d.ts.map +1 -0
- package/dist/components/FlowchartView/useSubflowNavigation.js +80 -0
- package/dist/components/FlowchartView/useSubflowNavigation.js.map +1 -0
- package/dist/components/GanttTimeline/GanttTimeline.d.ts +18 -0
- package/dist/components/GanttTimeline/GanttTimeline.d.ts.map +1 -0
- package/dist/components/GanttTimeline/GanttTimeline.js +123 -0
- package/dist/components/GanttTimeline/GanttTimeline.js.map +1 -0
- package/dist/components/GanttTimeline/index.d.ts +3 -0
- package/dist/components/GanttTimeline/index.d.ts.map +1 -0
- package/dist/components/GanttTimeline/index.js +2 -0
- package/dist/components/GanttTimeline/index.js.map +1 -0
- package/dist/components/MemoryInspector/MemoryInspector.d.ts +19 -0
- package/dist/components/MemoryInspector/MemoryInspector.d.ts.map +1 -0
- package/dist/components/MemoryInspector/MemoryInspector.js +95 -0
- package/dist/components/MemoryInspector/MemoryInspector.js.map +1 -0
- package/dist/components/MemoryInspector/index.d.ts +3 -0
- package/dist/components/MemoryInspector/index.d.ts.map +1 -0
- package/dist/components/MemoryInspector/index.js +2 -0
- package/dist/components/MemoryInspector/index.js.map +1 -0
- package/dist/components/NarrativeLog/NarrativeLog.d.ts +15 -0
- package/dist/components/NarrativeLog/NarrativeLog.d.ts.map +1 -0
- package/dist/components/NarrativeLog/NarrativeLog.js +65 -0
- package/dist/components/NarrativeLog/NarrativeLog.js.map +1 -0
- package/dist/components/NarrativeLog/index.d.ts +3 -0
- package/dist/components/NarrativeLog/index.d.ts.map +1 -0
- package/dist/components/NarrativeLog/index.js +2 -0
- package/dist/components/NarrativeLog/index.js.map +1 -0
- package/dist/components/NarrativeTrace/NarrativeTrace.d.ts +13 -0
- package/dist/components/NarrativeTrace/NarrativeTrace.d.ts.map +1 -0
- package/dist/components/NarrativeTrace/NarrativeTrace.js +127 -0
- package/dist/components/NarrativeTrace/NarrativeTrace.js.map +1 -0
- package/dist/components/NarrativeTrace/index.d.ts +3 -0
- package/dist/components/NarrativeTrace/index.d.ts.map +1 -0
- package/dist/components/NarrativeTrace/index.js +2 -0
- package/dist/components/NarrativeTrace/index.js.map +1 -0
- package/dist/components/ResultPanel/ResultPanel.d.ts +11 -0
- package/dist/components/ResultPanel/ResultPanel.d.ts.map +1 -0
- package/dist/components/ResultPanel/ResultPanel.js +54 -0
- package/dist/components/ResultPanel/ResultPanel.js.map +1 -0
- package/dist/components/ResultPanel/index.d.ts +3 -0
- package/dist/components/ResultPanel/index.d.ts.map +1 -0
- package/dist/components/ResultPanel/index.js +2 -0
- package/dist/components/ResultPanel/index.js.map +1 -0
- package/dist/components/ScopeDiff/ScopeDiff.d.ts +17 -0
- package/dist/components/ScopeDiff/ScopeDiff.d.ts.map +1 -0
- package/dist/components/ScopeDiff/ScopeDiff.js +87 -0
- package/dist/components/ScopeDiff/ScopeDiff.js.map +1 -0
- package/dist/components/ScopeDiff/index.d.ts +3 -0
- package/dist/components/ScopeDiff/index.d.ts.map +1 -0
- package/dist/components/ScopeDiff/index.js +2 -0
- package/dist/components/ScopeDiff/index.js.map +1 -0
- package/dist/components/SnapshotPanel/SnapshotPanel.d.ts +17 -0
- package/dist/components/SnapshotPanel/SnapshotPanel.d.ts.map +1 -0
- package/dist/components/SnapshotPanel/SnapshotPanel.js +85 -0
- package/dist/components/SnapshotPanel/SnapshotPanel.js.map +1 -0
- package/dist/components/SnapshotPanel/index.d.ts +3 -0
- package/dist/components/SnapshotPanel/index.d.ts.map +1 -0
- package/dist/components/SnapshotPanel/index.js +2 -0
- package/dist/components/SnapshotPanel/index.js.map +1 -0
- package/dist/components/StageNode/StageNode.d.ts +31 -0
- package/dist/components/StageNode/StageNode.d.ts.map +1 -0
- package/dist/components/StageNode/StageNode.js +134 -0
- package/dist/components/StageNode/StageNode.js.map +1 -0
- package/dist/components/StageNode/index.d.ts +3 -0
- package/dist/components/StageNode/index.d.ts.map +1 -0
- package/dist/components/StageNode/index.js +2 -0
- package/dist/components/StageNode/index.js.map +1 -0
- package/dist/components/TimeTravelControls/TimeTravelControls.d.ts +13 -0
- package/dist/components/TimeTravelControls/TimeTravelControls.d.ts.map +1 -0
- package/dist/components/TimeTravelControls/TimeTravelControls.js +104 -0
- package/dist/components/TimeTravelControls/TimeTravelControls.js.map +1 -0
- package/dist/components/TimeTravelControls/index.d.ts +3 -0
- package/dist/components/TimeTravelControls/index.d.ts.map +1 -0
- package/dist/components/TimeTravelControls/index.js +2 -0
- package/dist/components/TimeTravelControls/index.js.map +1 -0
- package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts +22 -0
- package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts.map +1 -0
- package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js +104 -0
- package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js.map +1 -0
- package/dist/components/TimeTravelDebugger/index.d.ts +3 -0
- package/dist/components/TimeTravelDebugger/index.d.ts.map +1 -0
- package/dist/components/TimeTravelDebugger/index.js +2 -0
- package/dist/components/TimeTravelDebugger/index.js.map +1 -0
- package/dist/flowchart.cjs +704 -220
- package/dist/flowchart.cjs.map +1 -1
- package/dist/flowchart.d.cts +55 -1
- package/dist/flowchart.d.ts +55 -1
- package/dist/flowchart.d.ts.map +1 -0
- package/dist/flowchart.js +700 -214
- package/dist/flowchart.js.map +1 -1
- package/dist/index.cjs +849 -76
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -3
- package/dist/index.d.ts +95 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +851 -80
- package/dist/index.js.map +1 -1
- package/dist/theme/ThemeProvider.d.ts +13 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +16 -0
- package/dist/theme/ThemeProvider.js.map +1 -0
- package/dist/theme/index.d.ts +7 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +5 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/presets.d.ts +15 -0
- package/dist/theme/presets.d.ts.map +1 -0
- package/dist/theme/presets.js +70 -0
- package/dist/theme/presets.js.map +1 -0
- package/dist/theme/styles.d.ts +32 -0
- package/dist/theme/styles.d.ts.map +1 -0
- package/dist/theme/styles.js +37 -0
- package/dist/theme/styles.js.map +1 -0
- package/dist/theme/tokens.d.ts +28 -0
- package/dist/theme/tokens.d.ts.map +1 -0
- package/dist/theme/tokens.js +58 -0
- package/dist/theme/tokens.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +10 -4
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,8 @@ __export(src_exports, {
|
|
|
29
29
|
ResultPanel: () => ResultPanel,
|
|
30
30
|
ScopeDiff: () => ScopeDiff,
|
|
31
31
|
SnapshotPanel: () => SnapshotPanel,
|
|
32
|
+
StageDetailPanel: () => StageDetailPanel,
|
|
33
|
+
SubflowTree: () => SubflowTree,
|
|
32
34
|
TimeTravelControls: () => TimeTravelControls,
|
|
33
35
|
coolDark: () => coolDark,
|
|
34
36
|
createSnapshots: () => createSnapshots,
|
|
@@ -697,8 +699,12 @@ function GanttTimeline({
|
|
|
697
699
|
size = "default",
|
|
698
700
|
unstyled = false,
|
|
699
701
|
className,
|
|
700
|
-
style
|
|
702
|
+
style,
|
|
703
|
+
maxVisibleRows = 5
|
|
701
704
|
}) {
|
|
705
|
+
const [expanded, setExpanded] = (0, import_react5.useState)(false);
|
|
706
|
+
const activeRowRef = (0, import_react5.useRef)(null);
|
|
707
|
+
const scrollContainerRef = (0, import_react5.useRef)(null);
|
|
702
708
|
const totalWallTime = (0, import_react5.useMemo)(
|
|
703
709
|
() => Math.max(...snapshots.map((s) => s.startMs + s.durationMs), 1),
|
|
704
710
|
[snapshots]
|
|
@@ -707,6 +713,17 @@ function GanttTimeline({
|
|
|
707
713
|
const pad = padding[size];
|
|
708
714
|
const labelWidth = size === "compact" ? 50 : size === "detailed" ? 100 : 80;
|
|
709
715
|
const msWidth = size === "compact" ? 28 : 36;
|
|
716
|
+
const rowHeight = size === "compact" ? 18 : 22;
|
|
717
|
+
const collapsible = maxVisibleRows > 0 && snapshots.length > maxVisibleRows;
|
|
718
|
+
const showAll = expanded || !collapsible;
|
|
719
|
+
(0, import_react5.useEffect)(() => {
|
|
720
|
+
if (!showAll && activeRowRef.current && scrollContainerRef.current) {
|
|
721
|
+
activeRowRef.current.scrollIntoView({
|
|
722
|
+
block: "nearest",
|
|
723
|
+
behavior: "smooth"
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
}, [selectedIndex, showAll]);
|
|
710
727
|
if (unstyled) {
|
|
711
728
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className, style, "data-fp": "gantt-timeline", children: snapshots.map((snap, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
712
729
|
"div",
|
|
@@ -733,27 +750,62 @@ function GanttTimeline({
|
|
|
733
750
|
style: { padding: pad, fontFamily: theme.fontSans, ...style },
|
|
734
751
|
"data-fp": "gantt-timeline",
|
|
735
752
|
children: [
|
|
736
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.
|
|
737
|
-
"
|
|
753
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
754
|
+
"div",
|
|
738
755
|
{
|
|
739
756
|
style: {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
textTransform: "uppercase",
|
|
744
|
-
letterSpacing: "0.08em"
|
|
757
|
+
display: "flex",
|
|
758
|
+
alignItems: "center",
|
|
759
|
+
justifyContent: "space-between"
|
|
745
760
|
},
|
|
746
|
-
children:
|
|
761
|
+
children: [
|
|
762
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
763
|
+
"span",
|
|
764
|
+
{
|
|
765
|
+
style: {
|
|
766
|
+
fontSize: fs.label,
|
|
767
|
+
fontWeight: 600,
|
|
768
|
+
color: theme.textMuted,
|
|
769
|
+
textTransform: "uppercase",
|
|
770
|
+
letterSpacing: "0.08em"
|
|
771
|
+
},
|
|
772
|
+
children: size === "compact" ? "Timeline" : "Execution Timeline"
|
|
773
|
+
}
|
|
774
|
+
),
|
|
775
|
+
collapsible && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
776
|
+
"button",
|
|
777
|
+
{
|
|
778
|
+
onClick: () => setExpanded((e) => !e),
|
|
779
|
+
style: {
|
|
780
|
+
background: "none",
|
|
781
|
+
border: `1px solid ${theme.border}`,
|
|
782
|
+
borderRadius: 4,
|
|
783
|
+
color: theme.textSecondary,
|
|
784
|
+
fontSize: fs.small,
|
|
785
|
+
padding: "2px 8px",
|
|
786
|
+
cursor: "pointer",
|
|
787
|
+
fontFamily: theme.fontSans
|
|
788
|
+
},
|
|
789
|
+
children: expanded ? "Collapse" : `${snapshots.length - maxVisibleRows} more...`
|
|
790
|
+
}
|
|
791
|
+
)
|
|
792
|
+
]
|
|
747
793
|
}
|
|
748
794
|
),
|
|
749
795
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
750
796
|
"div",
|
|
751
797
|
{
|
|
798
|
+
ref: scrollContainerRef,
|
|
752
799
|
style: {
|
|
753
800
|
marginTop: 8,
|
|
754
801
|
display: "flex",
|
|
755
802
|
flexDirection: "column",
|
|
756
|
-
gap: 4
|
|
803
|
+
gap: 4,
|
|
804
|
+
...showAll ? {} : {
|
|
805
|
+
maxHeight: maxVisibleRows * (rowHeight + 4),
|
|
806
|
+
overflowY: "auto",
|
|
807
|
+
scrollbarWidth: "thin"
|
|
808
|
+
}
|
|
757
809
|
},
|
|
758
810
|
children: snapshots.map((snap, idx) => {
|
|
759
811
|
const leftPct = snap.startMs / totalWallTime * 100;
|
|
@@ -763,6 +815,7 @@ function GanttTimeline({
|
|
|
763
815
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
764
816
|
"div",
|
|
765
817
|
{
|
|
818
|
+
ref: isSelected ? activeRowRef : void 0,
|
|
766
819
|
onClick: () => onSelect?.(idx),
|
|
767
820
|
style: {
|
|
768
821
|
display: "flex",
|
|
@@ -770,7 +823,9 @@ function GanttTimeline({
|
|
|
770
823
|
gap: size === "compact" ? 4 : 8,
|
|
771
824
|
cursor: onSelect ? "pointer" : "default",
|
|
772
825
|
opacity: isVisible ? 1 : 0.3,
|
|
773
|
-
transition: "opacity 0.3s ease"
|
|
826
|
+
transition: "opacity 0.3s ease",
|
|
827
|
+
height: rowHeight,
|
|
828
|
+
flexShrink: 0
|
|
774
829
|
},
|
|
775
830
|
children: [
|
|
776
831
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
@@ -1374,9 +1429,487 @@ function ResultPanel({
|
|
|
1374
1429
|
);
|
|
1375
1430
|
}
|
|
1376
1431
|
|
|
1377
|
-
// src/components/
|
|
1432
|
+
// src/components/StageDetailPanel/StageDetailPanel.tsx
|
|
1378
1433
|
var import_react8 = require("react");
|
|
1379
1434
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1435
|
+
function computeChanges(prev, curr) {
|
|
1436
|
+
const changes = [];
|
|
1437
|
+
const allKeys = /* @__PURE__ */ new Set([...Object.keys(prev ?? {}), ...Object.keys(curr)]);
|
|
1438
|
+
for (const key of allKeys) {
|
|
1439
|
+
const inPrev = prev != null && key in prev;
|
|
1440
|
+
const inCurr = key in curr;
|
|
1441
|
+
const oldVal = prev?.[key];
|
|
1442
|
+
const newVal = curr[key];
|
|
1443
|
+
if (!inPrev && inCurr) {
|
|
1444
|
+
changes.push({ key, type: "added", newValue: newVal });
|
|
1445
|
+
} else if (inPrev && !inCurr) {
|
|
1446
|
+
changes.push({ key, type: "removed", oldValue: oldVal });
|
|
1447
|
+
} else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
|
|
1448
|
+
changes.push({ key, type: "updated", oldValue: oldVal, newValue: newVal });
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
const order = { added: 0, updated: 1, removed: 2 };
|
|
1452
|
+
changes.sort((a, b) => order[a.type] - order[b.type]);
|
|
1453
|
+
return changes;
|
|
1454
|
+
}
|
|
1455
|
+
function fmt2(v2) {
|
|
1456
|
+
if (typeof v2 === "string") return `"${v2}"`;
|
|
1457
|
+
if (typeof v2 === "object" && v2 !== null) return JSON.stringify(v2, null, 2);
|
|
1458
|
+
return String(v2);
|
|
1459
|
+
}
|
|
1460
|
+
var changeBadge = {
|
|
1461
|
+
added: { bg: "rgba(34,197,94,0.12)", fg: "#22c55e", label: "ADD" },
|
|
1462
|
+
updated: { bg: "rgba(245,158,11,0.12)", fg: "#f59e0b", label: "UPD" },
|
|
1463
|
+
removed: { bg: "rgba(239,68,68,0.12)", fg: "#ef4444", label: "DEL" }
|
|
1464
|
+
};
|
|
1465
|
+
function SimpleView({
|
|
1466
|
+
snapshot,
|
|
1467
|
+
fs,
|
|
1468
|
+
pad
|
|
1469
|
+
}) {
|
|
1470
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
|
|
1471
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
1472
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1473
|
+
"div",
|
|
1474
|
+
{
|
|
1475
|
+
style: {
|
|
1476
|
+
fontSize: fs.label + 2,
|
|
1477
|
+
fontWeight: 700,
|
|
1478
|
+
color: theme.textPrimary
|
|
1479
|
+
},
|
|
1480
|
+
children: snapshot.stageLabel
|
|
1481
|
+
}
|
|
1482
|
+
),
|
|
1483
|
+
snapshot.description && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1484
|
+
"div",
|
|
1485
|
+
{
|
|
1486
|
+
style: {
|
|
1487
|
+
fontSize: fs.body,
|
|
1488
|
+
color: theme.textSecondary,
|
|
1489
|
+
marginTop: 4,
|
|
1490
|
+
lineHeight: 1.5
|
|
1491
|
+
},
|
|
1492
|
+
children: snapshot.description
|
|
1493
|
+
}
|
|
1494
|
+
)
|
|
1495
|
+
] }),
|
|
1496
|
+
snapshot.status && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
1497
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1498
|
+
"div",
|
|
1499
|
+
{
|
|
1500
|
+
style: {
|
|
1501
|
+
width: 8,
|
|
1502
|
+
height: 8,
|
|
1503
|
+
borderRadius: "50%",
|
|
1504
|
+
background: snapshot.status === "done" ? theme.success : snapshot.status === "active" ? theme.primary : snapshot.status === "error" ? theme.error : theme.textMuted
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
),
|
|
1508
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1509
|
+
"span",
|
|
1510
|
+
{
|
|
1511
|
+
style: {
|
|
1512
|
+
fontSize: fs.small,
|
|
1513
|
+
color: theme.textMuted,
|
|
1514
|
+
textTransform: "uppercase",
|
|
1515
|
+
letterSpacing: "0.05em"
|
|
1516
|
+
},
|
|
1517
|
+
children: snapshot.status
|
|
1518
|
+
}
|
|
1519
|
+
)
|
|
1520
|
+
] }),
|
|
1521
|
+
snapshot.narrative && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
1522
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1523
|
+
"div",
|
|
1524
|
+
{
|
|
1525
|
+
style: {
|
|
1526
|
+
fontSize: fs.label,
|
|
1527
|
+
fontWeight: 600,
|
|
1528
|
+
color: theme.textMuted,
|
|
1529
|
+
textTransform: "uppercase",
|
|
1530
|
+
letterSpacing: "0.08em",
|
|
1531
|
+
marginBottom: 6
|
|
1532
|
+
},
|
|
1533
|
+
children: "What happened"
|
|
1534
|
+
}
|
|
1535
|
+
),
|
|
1536
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1537
|
+
"div",
|
|
1538
|
+
{
|
|
1539
|
+
style: {
|
|
1540
|
+
fontSize: fs.body,
|
|
1541
|
+
lineHeight: 1.6,
|
|
1542
|
+
color: theme.textPrimary,
|
|
1543
|
+
background: theme.bgSecondary,
|
|
1544
|
+
border: `1px solid ${theme.border}`,
|
|
1545
|
+
borderRadius: theme.radius,
|
|
1546
|
+
padding: pad
|
|
1547
|
+
},
|
|
1548
|
+
children: snapshot.narrative
|
|
1549
|
+
}
|
|
1550
|
+
)
|
|
1551
|
+
] }),
|
|
1552
|
+
snapshot.durationMs > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1553
|
+
"div",
|
|
1554
|
+
{
|
|
1555
|
+
style: {
|
|
1556
|
+
fontSize: fs.small,
|
|
1557
|
+
color: theme.textMuted
|
|
1558
|
+
},
|
|
1559
|
+
children: [
|
|
1560
|
+
"Completed in ",
|
|
1561
|
+
snapshot.durationMs < 1 ? "<1" : snapshot.durationMs,
|
|
1562
|
+
"ms"
|
|
1563
|
+
]
|
|
1564
|
+
}
|
|
1565
|
+
)
|
|
1566
|
+
] });
|
|
1567
|
+
}
|
|
1568
|
+
function buildMemoryRows(currMemory, changes) {
|
|
1569
|
+
const changeMap = new Map(changes.map((c) => [c.key, c]));
|
|
1570
|
+
const rows = [];
|
|
1571
|
+
for (const change of changes) {
|
|
1572
|
+
rows.push({ kind: "change", change });
|
|
1573
|
+
}
|
|
1574
|
+
const unchangedKeys = Object.keys(currMemory).filter((k) => !changeMap.has(k)).sort();
|
|
1575
|
+
for (const key of unchangedKeys) {
|
|
1576
|
+
rows.push({ kind: "unchanged", key, value: currMemory[key] });
|
|
1577
|
+
}
|
|
1578
|
+
return rows;
|
|
1579
|
+
}
|
|
1580
|
+
function DevView({
|
|
1581
|
+
snapshot,
|
|
1582
|
+
changes,
|
|
1583
|
+
currMemory,
|
|
1584
|
+
fs,
|
|
1585
|
+
pad
|
|
1586
|
+
}) {
|
|
1587
|
+
const rows = (0, import_react8.useMemo)(() => buildMemoryRows(currMemory, changes), [currMemory, changes]);
|
|
1588
|
+
const totalKeys = Object.keys(currMemory).length;
|
|
1589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
|
|
1590
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
1591
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1592
|
+
"span",
|
|
1593
|
+
{
|
|
1594
|
+
style: {
|
|
1595
|
+
fontSize: fs.label + 2,
|
|
1596
|
+
fontWeight: 700,
|
|
1597
|
+
color: theme.textPrimary,
|
|
1598
|
+
fontFamily: theme.fontMono
|
|
1599
|
+
},
|
|
1600
|
+
children: snapshot.stageLabel
|
|
1601
|
+
}
|
|
1602
|
+
),
|
|
1603
|
+
snapshot.durationMs > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1604
|
+
"span",
|
|
1605
|
+
{
|
|
1606
|
+
style: {
|
|
1607
|
+
fontSize: fs.small,
|
|
1608
|
+
color: theme.textMuted,
|
|
1609
|
+
fontFamily: theme.fontMono
|
|
1610
|
+
},
|
|
1611
|
+
children: [
|
|
1612
|
+
snapshot.durationMs,
|
|
1613
|
+
"ms"
|
|
1614
|
+
]
|
|
1615
|
+
}
|
|
1616
|
+
)
|
|
1617
|
+
] }),
|
|
1618
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1619
|
+
"div",
|
|
1620
|
+
{
|
|
1621
|
+
style: {
|
|
1622
|
+
fontSize: fs.label,
|
|
1623
|
+
fontWeight: 600,
|
|
1624
|
+
color: theme.textMuted,
|
|
1625
|
+
textTransform: "uppercase",
|
|
1626
|
+
letterSpacing: "0.08em"
|
|
1627
|
+
},
|
|
1628
|
+
children: [
|
|
1629
|
+
"Memory",
|
|
1630
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { style: { fontWeight: 400, marginLeft: 6 }, children: [
|
|
1631
|
+
"(",
|
|
1632
|
+
totalKeys,
|
|
1633
|
+
" key",
|
|
1634
|
+
totalKeys !== 1 ? "s" : "",
|
|
1635
|
+
changes.length > 0 && `, ${changes.length} changed`,
|
|
1636
|
+
")"
|
|
1637
|
+
] })
|
|
1638
|
+
]
|
|
1639
|
+
}
|
|
1640
|
+
),
|
|
1641
|
+
rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1642
|
+
"div",
|
|
1643
|
+
{
|
|
1644
|
+
style: {
|
|
1645
|
+
fontSize: fs.body,
|
|
1646
|
+
color: theme.textMuted,
|
|
1647
|
+
fontStyle: "italic",
|
|
1648
|
+
fontFamily: theme.fontMono,
|
|
1649
|
+
padding: `${pad}px`,
|
|
1650
|
+
background: theme.bgSecondary,
|
|
1651
|
+
borderRadius: theme.radius
|
|
1652
|
+
},
|
|
1653
|
+
children: "Empty memory"
|
|
1654
|
+
}
|
|
1655
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1656
|
+
"div",
|
|
1657
|
+
{
|
|
1658
|
+
style: {
|
|
1659
|
+
fontFamily: theme.fontMono,
|
|
1660
|
+
fontSize: fs.body,
|
|
1661
|
+
background: theme.bgSecondary,
|
|
1662
|
+
border: `1px solid ${theme.border}`,
|
|
1663
|
+
borderRadius: theme.radius,
|
|
1664
|
+
overflow: "hidden"
|
|
1665
|
+
},
|
|
1666
|
+
children: rows.map((row) => {
|
|
1667
|
+
if (row.kind === "change") {
|
|
1668
|
+
const { change } = row;
|
|
1669
|
+
const badge = changeBadge[change.type];
|
|
1670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1671
|
+
"div",
|
|
1672
|
+
{
|
|
1673
|
+
style: {
|
|
1674
|
+
display: "flex",
|
|
1675
|
+
alignItems: "flex-start",
|
|
1676
|
+
gap: 8,
|
|
1677
|
+
padding: `6px ${pad}px`,
|
|
1678
|
+
borderBottom: `1px solid ${theme.border}`,
|
|
1679
|
+
background: badge.bg
|
|
1680
|
+
},
|
|
1681
|
+
"data-fp": "memory-change",
|
|
1682
|
+
"data-type": change.type,
|
|
1683
|
+
children: [
|
|
1684
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1685
|
+
"span",
|
|
1686
|
+
{
|
|
1687
|
+
style: {
|
|
1688
|
+
fontSize: fs.small,
|
|
1689
|
+
fontWeight: 700,
|
|
1690
|
+
color: badge.fg,
|
|
1691
|
+
width: 28,
|
|
1692
|
+
flexShrink: 0,
|
|
1693
|
+
textAlign: "center",
|
|
1694
|
+
lineHeight: 1.8
|
|
1695
|
+
},
|
|
1696
|
+
children: badge.label
|
|
1697
|
+
}
|
|
1698
|
+
),
|
|
1699
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1700
|
+
"span",
|
|
1701
|
+
{
|
|
1702
|
+
style: {
|
|
1703
|
+
color: theme.primary,
|
|
1704
|
+
fontWeight: 600,
|
|
1705
|
+
flexShrink: 0,
|
|
1706
|
+
lineHeight: 1.8
|
|
1707
|
+
},
|
|
1708
|
+
children: change.key
|
|
1709
|
+
}
|
|
1710
|
+
),
|
|
1711
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { flex: 1, minWidth: 0, lineHeight: 1.8 }, children: change.type === "updated" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1712
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1713
|
+
"span",
|
|
1714
|
+
{
|
|
1715
|
+
style: {
|
|
1716
|
+
color: theme.error,
|
|
1717
|
+
textDecoration: "line-through",
|
|
1718
|
+
opacity: 0.7
|
|
1719
|
+
},
|
|
1720
|
+
children: fmt2(change.oldValue)
|
|
1721
|
+
}
|
|
1722
|
+
),
|
|
1723
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: theme.textMuted, margin: "0 4px" }, children: "\u2192" }),
|
|
1724
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: theme.success }, children: fmt2(change.newValue) })
|
|
1725
|
+
] }) : change.type === "added" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: theme.success }, children: fmt2(change.newValue) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { color: theme.error, textDecoration: "line-through" }, children: fmt2(change.oldValue) }) })
|
|
1726
|
+
]
|
|
1727
|
+
},
|
|
1728
|
+
change.key
|
|
1729
|
+
);
|
|
1730
|
+
}
|
|
1731
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1732
|
+
"div",
|
|
1733
|
+
{
|
|
1734
|
+
style: {
|
|
1735
|
+
display: "flex",
|
|
1736
|
+
alignItems: "flex-start",
|
|
1737
|
+
gap: 8,
|
|
1738
|
+
padding: `6px ${pad}px`,
|
|
1739
|
+
borderBottom: `1px solid ${theme.border}`,
|
|
1740
|
+
opacity: 0.5
|
|
1741
|
+
},
|
|
1742
|
+
"data-fp": "memory-unchanged",
|
|
1743
|
+
children: [
|
|
1744
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1745
|
+
"span",
|
|
1746
|
+
{
|
|
1747
|
+
style: {
|
|
1748
|
+
width: 28,
|
|
1749
|
+
flexShrink: 0,
|
|
1750
|
+
lineHeight: 1.8
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
),
|
|
1754
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1755
|
+
"span",
|
|
1756
|
+
{
|
|
1757
|
+
style: {
|
|
1758
|
+
color: theme.textSecondary,
|
|
1759
|
+
fontWeight: 500,
|
|
1760
|
+
flexShrink: 0,
|
|
1761
|
+
lineHeight: 1.8
|
|
1762
|
+
},
|
|
1763
|
+
children: row.key
|
|
1764
|
+
}
|
|
1765
|
+
),
|
|
1766
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { flex: 1, minWidth: 0, lineHeight: 1.8, color: theme.textMuted }, children: fmt2(row.value) })
|
|
1767
|
+
]
|
|
1768
|
+
},
|
|
1769
|
+
row.key
|
|
1770
|
+
);
|
|
1771
|
+
})
|
|
1772
|
+
}
|
|
1773
|
+
)
|
|
1774
|
+
] });
|
|
1775
|
+
}
|
|
1776
|
+
function UnstyledSimpleView({ snapshot }) {
|
|
1777
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { "data-fp": "stage-detail-simple", children: [
|
|
1778
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-fp": "stage-label", children: snapshot.stageLabel }),
|
|
1779
|
+
snapshot.description && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-fp": "stage-description", children: snapshot.description }),
|
|
1780
|
+
snapshot.status && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-fp": "stage-status", children: snapshot.status }),
|
|
1781
|
+
snapshot.narrative && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-fp": "stage-narrative", children: snapshot.narrative })
|
|
1782
|
+
] });
|
|
1783
|
+
}
|
|
1784
|
+
function UnstyledDevView({
|
|
1785
|
+
snapshot,
|
|
1786
|
+
changes,
|
|
1787
|
+
currMemory
|
|
1788
|
+
}) {
|
|
1789
|
+
const rows = (0, import_react8.useMemo)(() => buildMemoryRows(currMemory, changes), [currMemory, changes]);
|
|
1790
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { "data-fp": "stage-detail-dev", children: [
|
|
1791
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-fp": "stage-label", children: snapshot.stageLabel }),
|
|
1792
|
+
rows.map((row) => {
|
|
1793
|
+
if (row.kind === "change") {
|
|
1794
|
+
const c = row.change;
|
|
1795
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { "data-fp": "memory-change", "data-type": c.type, children: [
|
|
1796
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-fp": "change-key", children: c.key }),
|
|
1797
|
+
c.type === "updated" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1798
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-fp": "change-old", children: fmt2(c.oldValue) }),
|
|
1799
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-fp": "change-new", children: fmt2(c.newValue) })
|
|
1800
|
+
] }),
|
|
1801
|
+
c.type === "added" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-fp": "change-value", children: fmt2(c.newValue) }),
|
|
1802
|
+
c.type === "removed" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-fp": "change-value", children: fmt2(c.oldValue) })
|
|
1803
|
+
] }, c.key);
|
|
1804
|
+
}
|
|
1805
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { "data-fp": "memory-unchanged", children: [
|
|
1806
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-fp": "unchanged-key", children: row.key }),
|
|
1807
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-fp": "unchanged-value", children: fmt2(row.value) })
|
|
1808
|
+
] }, row.key);
|
|
1809
|
+
})
|
|
1810
|
+
] });
|
|
1811
|
+
}
|
|
1812
|
+
function ModeToggle({
|
|
1813
|
+
activeMode,
|
|
1814
|
+
onToggle,
|
|
1815
|
+
fs,
|
|
1816
|
+
unstyled
|
|
1817
|
+
}) {
|
|
1818
|
+
if (unstyled) {
|
|
1819
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { "data-fp": "mode-toggle", "data-mode": activeMode, onClick: onToggle, children: activeMode === "simple" ? "Dev" : "Simple" });
|
|
1820
|
+
}
|
|
1821
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1822
|
+
"div",
|
|
1823
|
+
{
|
|
1824
|
+
style: {
|
|
1825
|
+
display: "inline-flex",
|
|
1826
|
+
borderRadius: 6,
|
|
1827
|
+
border: `1px solid ${theme.border}`,
|
|
1828
|
+
overflow: "hidden",
|
|
1829
|
+
flexShrink: 0
|
|
1830
|
+
},
|
|
1831
|
+
"data-fp": "mode-toggle",
|
|
1832
|
+
children: ["simple", "dev"].map((m) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1833
|
+
"button",
|
|
1834
|
+
{
|
|
1835
|
+
onClick: m !== activeMode ? onToggle : void 0,
|
|
1836
|
+
style: {
|
|
1837
|
+
padding: "4px 10px",
|
|
1838
|
+
fontSize: fs.small,
|
|
1839
|
+
fontWeight: m === activeMode ? 700 : 400,
|
|
1840
|
+
textTransform: "uppercase",
|
|
1841
|
+
letterSpacing: "0.05em",
|
|
1842
|
+
color: m === activeMode ? theme.textPrimary : theme.textMuted,
|
|
1843
|
+
background: m === activeMode ? theme.bgTertiary : "transparent",
|
|
1844
|
+
border: "none",
|
|
1845
|
+
cursor: m === activeMode ? "default" : "pointer"
|
|
1846
|
+
},
|
|
1847
|
+
children: m === "simple" ? "Simple" : "Dev"
|
|
1848
|
+
},
|
|
1849
|
+
m
|
|
1850
|
+
))
|
|
1851
|
+
}
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1854
|
+
function StageDetailPanel({
|
|
1855
|
+
snapshots,
|
|
1856
|
+
selectedIndex,
|
|
1857
|
+
mode: controlledMode,
|
|
1858
|
+
showToggle = false,
|
|
1859
|
+
onModeChange,
|
|
1860
|
+
size = "default",
|
|
1861
|
+
unstyled = false,
|
|
1862
|
+
className,
|
|
1863
|
+
style
|
|
1864
|
+
}) {
|
|
1865
|
+
const [internalMode, setInternalMode] = (0, import_react8.useState)(controlledMode ?? "simple");
|
|
1866
|
+
const activeMode = controlledMode ?? internalMode;
|
|
1867
|
+
const handleToggle = (0, import_react8.useCallback)(() => {
|
|
1868
|
+
const next = activeMode === "simple" ? "dev" : "simple";
|
|
1869
|
+
setInternalMode(next);
|
|
1870
|
+
onModeChange?.(next);
|
|
1871
|
+
}, [activeMode, onModeChange]);
|
|
1872
|
+
const snapshot = snapshots[selectedIndex];
|
|
1873
|
+
const prevMemory = selectedIndex > 0 ? snapshots[selectedIndex - 1]?.memory ?? null : null;
|
|
1874
|
+
const currMemory = snapshot?.memory ?? {};
|
|
1875
|
+
const changes = (0, import_react8.useMemo)(
|
|
1876
|
+
() => computeChanges(prevMemory, currMemory),
|
|
1877
|
+
[prevMemory, currMemory]
|
|
1878
|
+
);
|
|
1879
|
+
const fs = fontSize[size];
|
|
1880
|
+
const pad = padding[size];
|
|
1881
|
+
if (!snapshot) {
|
|
1882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className, style, "data-fp": "stage-detail-panel", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: unstyled ? {} : { color: theme.textMuted, fontSize: fs.body, fontStyle: "italic", padding: pad }, children: "No stage selected" }) });
|
|
1883
|
+
}
|
|
1884
|
+
if (unstyled) {
|
|
1885
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className, style, "data-fp": "stage-detail-panel", "data-mode": activeMode, children: [
|
|
1886
|
+
showToggle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ModeToggle, { activeMode, onToggle: handleToggle, fs, unstyled: true }),
|
|
1887
|
+
activeMode === "simple" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(UnstyledSimpleView, { snapshot }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(UnstyledDevView, { snapshot, changes, currMemory })
|
|
1888
|
+
] });
|
|
1889
|
+
}
|
|
1890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1891
|
+
"div",
|
|
1892
|
+
{
|
|
1893
|
+
className,
|
|
1894
|
+
style: {
|
|
1895
|
+
padding: pad,
|
|
1896
|
+
fontFamily: theme.fontSans,
|
|
1897
|
+
overflow: "auto",
|
|
1898
|
+
...style
|
|
1899
|
+
},
|
|
1900
|
+
"data-fp": "stage-detail-panel",
|
|
1901
|
+
"data-mode": activeMode,
|
|
1902
|
+
children: [
|
|
1903
|
+
showToggle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", marginBottom: 12 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ModeToggle, { activeMode, onToggle: handleToggle, fs, unstyled: false }) }),
|
|
1904
|
+
activeMode === "simple" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SimpleView, { snapshot, fs, pad }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DevView, { snapshot, changes, currMemory, fs, pad })
|
|
1905
|
+
]
|
|
1906
|
+
}
|
|
1907
|
+
);
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
// src/components/TimeTravelControls/TimeTravelControls.tsx
|
|
1911
|
+
var import_react9 = require("react");
|
|
1912
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1380
1913
|
function TimeTravelControls({
|
|
1381
1914
|
snapshots,
|
|
1382
1915
|
selectedIndex,
|
|
@@ -1387,12 +1920,12 @@ function TimeTravelControls({
|
|
|
1387
1920
|
className,
|
|
1388
1921
|
style
|
|
1389
1922
|
}) {
|
|
1390
|
-
const [playing, setPlaying] = (0,
|
|
1391
|
-
const playRef = (0,
|
|
1923
|
+
const [playing, setPlaying] = (0, import_react9.useState)(false);
|
|
1924
|
+
const playRef = (0, import_react9.useRef)(null);
|
|
1392
1925
|
const total = snapshots.length;
|
|
1393
1926
|
const canPrev = selectedIndex > 0;
|
|
1394
1927
|
const canNext = selectedIndex < total - 1;
|
|
1395
|
-
(0,
|
|
1928
|
+
(0, import_react9.useEffect)(() => {
|
|
1396
1929
|
if (!playing || !autoPlayable) return;
|
|
1397
1930
|
if (selectedIndex >= total - 1) {
|
|
1398
1931
|
setPlaying(false);
|
|
@@ -1410,7 +1943,7 @@ function TimeTravelControls({
|
|
|
1410
1943
|
if (playRef.current) clearTimeout(playRef.current);
|
|
1411
1944
|
};
|
|
1412
1945
|
}, [playing, selectedIndex, snapshots, total, onIndexChange, autoPlayable]);
|
|
1413
|
-
const togglePlay = (0,
|
|
1946
|
+
const togglePlay = (0, import_react9.useCallback)(() => {
|
|
1414
1947
|
if (playing) {
|
|
1415
1948
|
setPlaying(false);
|
|
1416
1949
|
} else {
|
|
@@ -1420,8 +1953,8 @@ function TimeTravelControls({
|
|
|
1420
1953
|
}, [playing, selectedIndex, total, onIndexChange]);
|
|
1421
1954
|
const fs = fontSize[size];
|
|
1422
1955
|
if (unstyled) {
|
|
1423
|
-
return /* @__PURE__ */ (0,
|
|
1424
|
-
/* @__PURE__ */ (0,
|
|
1956
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className, style, "data-fp": "time-travel-controls", children: [
|
|
1957
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1425
1958
|
"button",
|
|
1426
1959
|
{
|
|
1427
1960
|
"data-fp": "tt-prev",
|
|
@@ -1433,8 +1966,8 @@ function TimeTravelControls({
|
|
|
1433
1966
|
children: "Prev"
|
|
1434
1967
|
}
|
|
1435
1968
|
),
|
|
1436
|
-
autoPlayable && /* @__PURE__ */ (0,
|
|
1437
|
-
/* @__PURE__ */ (0,
|
|
1969
|
+
autoPlayable && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { "data-fp": "tt-play", onClick: togglePlay, children: playing ? "Pause" : "Play" }),
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1438
1971
|
"button",
|
|
1439
1972
|
{
|
|
1440
1973
|
"data-fp": "tt-next",
|
|
@@ -1446,7 +1979,7 @@ function TimeTravelControls({
|
|
|
1446
1979
|
children: "Next"
|
|
1447
1980
|
}
|
|
1448
1981
|
),
|
|
1449
|
-
/* @__PURE__ */ (0,
|
|
1982
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-fp": "tt-ticks", children: snapshots.map((snap, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1450
1983
|
"button",
|
|
1451
1984
|
{
|
|
1452
1985
|
"data-fp": "tt-tick",
|
|
@@ -1474,7 +2007,7 @@ function TimeTravelControls({
|
|
|
1474
2007
|
opacity: disabled ? 0.5 : 1,
|
|
1475
2008
|
flexShrink: 0
|
|
1476
2009
|
});
|
|
1477
|
-
return /* @__PURE__ */ (0,
|
|
2010
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1478
2011
|
"div",
|
|
1479
2012
|
{
|
|
1480
2013
|
className,
|
|
@@ -1490,7 +2023,7 @@ function TimeTravelControls({
|
|
|
1490
2023
|
},
|
|
1491
2024
|
"data-fp": "time-travel-controls",
|
|
1492
2025
|
children: [
|
|
1493
|
-
/* @__PURE__ */ (0,
|
|
2026
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1494
2027
|
"button",
|
|
1495
2028
|
{
|
|
1496
2029
|
style: btnStyle(!canPrev || playing),
|
|
@@ -1502,7 +2035,7 @@ function TimeTravelControls({
|
|
|
1502
2035
|
children: "\u25C0"
|
|
1503
2036
|
}
|
|
1504
2037
|
),
|
|
1505
|
-
autoPlayable && /* @__PURE__ */ (0,
|
|
2038
|
+
autoPlayable && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1506
2039
|
"button",
|
|
1507
2040
|
{
|
|
1508
2041
|
onClick: togglePlay,
|
|
@@ -1524,7 +2057,7 @@ function TimeTravelControls({
|
|
|
1524
2057
|
children: playing ? "\u23F8" : "\u25B6"
|
|
1525
2058
|
}
|
|
1526
2059
|
),
|
|
1527
|
-
/* @__PURE__ */ (0,
|
|
2060
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1528
2061
|
"button",
|
|
1529
2062
|
{
|
|
1530
2063
|
style: btnStyle(!canNext || playing),
|
|
@@ -1536,7 +2069,7 @@ function TimeTravelControls({
|
|
|
1536
2069
|
children: "\u25B6"
|
|
1537
2070
|
}
|
|
1538
2071
|
),
|
|
1539
|
-
/* @__PURE__ */ (0,
|
|
2072
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1540
2073
|
"div",
|
|
1541
2074
|
{
|
|
1542
2075
|
style: {
|
|
@@ -1549,7 +2082,7 @@ function TimeTravelControls({
|
|
|
1549
2082
|
children: snapshots.map((snap, i) => {
|
|
1550
2083
|
const isActive = i === selectedIndex;
|
|
1551
2084
|
const isDone = i < selectedIndex;
|
|
1552
|
-
return /* @__PURE__ */ (0,
|
|
2085
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1553
2086
|
"button",
|
|
1554
2087
|
{
|
|
1555
2088
|
onClick: () => {
|
|
@@ -1579,8 +2112,8 @@ function TimeTravelControls({
|
|
|
1579
2112
|
}
|
|
1580
2113
|
|
|
1581
2114
|
// src/components/ExplainableShell/ExplainableShell.tsx
|
|
1582
|
-
var
|
|
1583
|
-
var
|
|
2115
|
+
var import_react10 = require("react");
|
|
2116
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1584
2117
|
function ExplainableShell({
|
|
1585
2118
|
snapshots,
|
|
1586
2119
|
resultData,
|
|
@@ -1595,14 +2128,14 @@ function ExplainableShell({
|
|
|
1595
2128
|
className,
|
|
1596
2129
|
style
|
|
1597
2130
|
}) {
|
|
1598
|
-
const [activeTab, setActiveTab] = (0,
|
|
1599
|
-
const [snapshotIdx, setSnapshotIdx] = (0,
|
|
2131
|
+
const [activeTab, setActiveTab] = (0, import_react10.useState)(defaultTab ?? tabs[0]);
|
|
2132
|
+
const [snapshotIdx, setSnapshotIdx] = (0, import_react10.useState)(0);
|
|
1600
2133
|
const fs = fontSize[size];
|
|
1601
2134
|
const pad = padding[size];
|
|
1602
|
-
const handleSnapshotChange = (0,
|
|
2135
|
+
const handleSnapshotChange = (0, import_react10.useCallback)((idx) => {
|
|
1603
2136
|
setSnapshotIdx(Math.max(0, Math.min(idx, snapshots.length - 1)));
|
|
1604
2137
|
}, [snapshots.length]);
|
|
1605
|
-
const revealedCount = (0,
|
|
2138
|
+
const revealedCount = (0, import_react10.useMemo)(() => {
|
|
1606
2139
|
if (snapshots.length === 0 || narrative.length === 0) return narrative.length;
|
|
1607
2140
|
const boundaries = [];
|
|
1608
2141
|
for (let i = 0; i < narrative.length; i++) {
|
|
@@ -1633,8 +2166,8 @@ function ExplainableShell({
|
|
|
1633
2166
|
"ai-compatible": "AI-Compatible"
|
|
1634
2167
|
};
|
|
1635
2168
|
if (unstyled) {
|
|
1636
|
-
return /* @__PURE__ */ (0,
|
|
1637
|
-
/* @__PURE__ */ (0,
|
|
2169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className, style, "data-fp": "explainable-shell", children: [
|
|
2170
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { "data-fp": "shell-tabs", children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1638
2171
|
"button",
|
|
1639
2172
|
{
|
|
1640
2173
|
"data-fp": "shell-tab",
|
|
@@ -1644,8 +2177,8 @@ function ExplainableShell({
|
|
|
1644
2177
|
},
|
|
1645
2178
|
tab
|
|
1646
2179
|
)) }),
|
|
1647
|
-
/* @__PURE__ */ (0,
|
|
1648
|
-
activeTab === "result" && /* @__PURE__ */ (0,
|
|
2180
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { "data-fp": "shell-content", "data-tab": activeTab, children: [
|
|
2181
|
+
activeTab === "result" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1649
2182
|
ResultPanel,
|
|
1650
2183
|
{
|
|
1651
2184
|
data: resultData ?? null,
|
|
@@ -1654,8 +2187,8 @@ function ExplainableShell({
|
|
|
1654
2187
|
unstyled: true
|
|
1655
2188
|
}
|
|
1656
2189
|
),
|
|
1657
|
-
activeTab === "explainable" && /* @__PURE__ */ (0,
|
|
1658
|
-
/* @__PURE__ */ (0,
|
|
2190
|
+
activeTab === "explainable" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2191
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1659
2192
|
TimeTravelControls,
|
|
1660
2193
|
{
|
|
1661
2194
|
snapshots,
|
|
@@ -1665,9 +2198,9 @@ function ExplainableShell({
|
|
|
1665
2198
|
}
|
|
1666
2199
|
),
|
|
1667
2200
|
renderFlowchart?.({ snapshots, selectedIndex: snapshotIdx, onNodeClick: handleSnapshotChange }),
|
|
1668
|
-
/* @__PURE__ */ (0,
|
|
1669
|
-
/* @__PURE__ */ (0,
|
|
1670
|
-
/* @__PURE__ */ (0,
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MemoryInspector, { snapshots, selectedIndex: snapshotIdx, unstyled: true }),
|
|
2202
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScopeDiff, { previous: prevMemory, current: currMemory, unstyled: true }),
|
|
2203
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1671
2204
|
GanttTimeline,
|
|
1672
2205
|
{
|
|
1673
2206
|
snapshots,
|
|
@@ -1677,8 +2210,8 @@ function ExplainableShell({
|
|
|
1677
2210
|
}
|
|
1678
2211
|
)
|
|
1679
2212
|
] }),
|
|
1680
|
-
activeTab === "ai-compatible" && /* @__PURE__ */ (0,
|
|
1681
|
-
/* @__PURE__ */ (0,
|
|
2213
|
+
activeTab === "ai-compatible" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1682
2215
|
TimeTravelControls,
|
|
1683
2216
|
{
|
|
1684
2217
|
snapshots,
|
|
@@ -1688,7 +2221,7 @@ function ExplainableShell({
|
|
|
1688
2221
|
}
|
|
1689
2222
|
),
|
|
1690
2223
|
renderFlowchart?.({ snapshots, selectedIndex: snapshotIdx, onNodeClick: handleSnapshotChange }),
|
|
1691
|
-
/* @__PURE__ */ (0,
|
|
2224
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1692
2225
|
NarrativeTrace,
|
|
1693
2226
|
{
|
|
1694
2227
|
narrative,
|
|
@@ -1700,7 +2233,7 @@ function ExplainableShell({
|
|
|
1700
2233
|
] })
|
|
1701
2234
|
] });
|
|
1702
2235
|
}
|
|
1703
|
-
return /* @__PURE__ */ (0,
|
|
2236
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1704
2237
|
"div",
|
|
1705
2238
|
{
|
|
1706
2239
|
className,
|
|
@@ -1716,7 +2249,7 @@ function ExplainableShell({
|
|
|
1716
2249
|
},
|
|
1717
2250
|
"data-fp": "explainable-shell",
|
|
1718
2251
|
children: [
|
|
1719
|
-
/* @__PURE__ */ (0,
|
|
2252
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1720
2253
|
"div",
|
|
1721
2254
|
{
|
|
1722
2255
|
style: {
|
|
@@ -1728,7 +2261,7 @@ function ExplainableShell({
|
|
|
1728
2261
|
},
|
|
1729
2262
|
children: tabs.map((tab) => {
|
|
1730
2263
|
const active = tab === activeTab;
|
|
1731
|
-
return /* @__PURE__ */ (0,
|
|
2264
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1732
2265
|
"button",
|
|
1733
2266
|
{
|
|
1734
2267
|
onClick: () => setActiveTab(tab),
|
|
@@ -1752,8 +2285,8 @@ function ExplainableShell({
|
|
|
1752
2285
|
})
|
|
1753
2286
|
}
|
|
1754
2287
|
),
|
|
1755
|
-
/* @__PURE__ */ (0,
|
|
1756
|
-
activeTab === "result" && /* @__PURE__ */ (0,
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { flex: 1, overflow: "hidden", display: "flex", flexDirection: "column" }, children: [
|
|
2289
|
+
activeTab === "result" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1757
2290
|
ResultPanel,
|
|
1758
2291
|
{
|
|
1759
2292
|
data: resultData ?? null,
|
|
@@ -1762,8 +2295,8 @@ function ExplainableShell({
|
|
|
1762
2295
|
size
|
|
1763
2296
|
}
|
|
1764
2297
|
),
|
|
1765
|
-
activeTab === "explainable" && /* @__PURE__ */ (0,
|
|
1766
|
-
/* @__PURE__ */ (0,
|
|
2298
|
+
activeTab === "explainable" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2299
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1767
2300
|
TimeTravelControls,
|
|
1768
2301
|
{
|
|
1769
2302
|
snapshots,
|
|
@@ -1772,9 +2305,9 @@ function ExplainableShell({
|
|
|
1772
2305
|
size
|
|
1773
2306
|
}
|
|
1774
2307
|
),
|
|
1775
|
-
/* @__PURE__ */ (0,
|
|
1776
|
-
renderFlowchart && /* @__PURE__ */ (0,
|
|
1777
|
-
/* @__PURE__ */ (0,
|
|
2308
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
|
|
2309
|
+
renderFlowchart && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { flex: 1, overflow: "hidden", borderRight: `1px solid ${theme.border}` }, children: renderFlowchart({ snapshots, selectedIndex: snapshotIdx, onNodeClick: handleSnapshotChange }) }),
|
|
2310
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1778
2311
|
"div",
|
|
1779
2312
|
{
|
|
1780
2313
|
style: {
|
|
@@ -1785,7 +2318,7 @@ function ExplainableShell({
|
|
|
1785
2318
|
flexDirection: "column"
|
|
1786
2319
|
},
|
|
1787
2320
|
children: [
|
|
1788
|
-
/* @__PURE__ */ (0,
|
|
2321
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1789
2322
|
MemoryInspector,
|
|
1790
2323
|
{
|
|
1791
2324
|
snapshots,
|
|
@@ -1793,7 +2326,7 @@ function ExplainableShell({
|
|
|
1793
2326
|
size
|
|
1794
2327
|
}
|
|
1795
2328
|
),
|
|
1796
|
-
/* @__PURE__ */ (0,
|
|
2329
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { borderTop: `1px solid ${theme.border}` }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1797
2330
|
ScopeDiff,
|
|
1798
2331
|
{
|
|
1799
2332
|
previous: prevMemory,
|
|
@@ -1806,7 +2339,7 @@ function ExplainableShell({
|
|
|
1806
2339
|
}
|
|
1807
2340
|
)
|
|
1808
2341
|
] }),
|
|
1809
|
-
/* @__PURE__ */ (0,
|
|
2342
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { borderTop: `1px solid ${theme.border}`, flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1810
2343
|
GanttTimeline,
|
|
1811
2344
|
{
|
|
1812
2345
|
snapshots,
|
|
@@ -1816,8 +2349,8 @@ function ExplainableShell({
|
|
|
1816
2349
|
}
|
|
1817
2350
|
) })
|
|
1818
2351
|
] }),
|
|
1819
|
-
activeTab === "ai-compatible" && /* @__PURE__ */ (0,
|
|
1820
|
-
/* @__PURE__ */ (0,
|
|
2352
|
+
activeTab === "ai-compatible" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2353
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1821
2354
|
TimeTravelControls,
|
|
1822
2355
|
{
|
|
1823
2356
|
snapshots,
|
|
@@ -1826,9 +2359,9 @@ function ExplainableShell({
|
|
|
1826
2359
|
size
|
|
1827
2360
|
}
|
|
1828
2361
|
),
|
|
1829
|
-
/* @__PURE__ */ (0,
|
|
1830
|
-
renderFlowchart && /* @__PURE__ */ (0,
|
|
1831
|
-
/* @__PURE__ */ (0,
|
|
2362
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
|
|
2363
|
+
renderFlowchart && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { flex: 1, overflow: "hidden", borderRight: `1px solid ${theme.border}` }, children: renderFlowchart({ snapshots, selectedIndex: snapshotIdx, onNodeClick: handleSnapshotChange }) }),
|
|
2364
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1832
2365
|
NarrativeTrace,
|
|
1833
2366
|
{
|
|
1834
2367
|
narrative,
|
|
@@ -1848,40 +2381,276 @@ function ExplainableShell({
|
|
|
1848
2381
|
);
|
|
1849
2382
|
}
|
|
1850
2383
|
|
|
2384
|
+
// src/components/FlowchartView/SubflowTree.tsx
|
|
2385
|
+
var import_react11 = require("react");
|
|
2386
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2387
|
+
function specToTree(node) {
|
|
2388
|
+
const entries = [];
|
|
2389
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2390
|
+
function walk(n) {
|
|
2391
|
+
const id = n.name || n.id || "";
|
|
2392
|
+
if (seen.has(id)) return;
|
|
2393
|
+
seen.add(id);
|
|
2394
|
+
const entry = {
|
|
2395
|
+
name: n.name,
|
|
2396
|
+
description: n.description,
|
|
2397
|
+
subflowId: n.subflowId,
|
|
2398
|
+
isSubflow: !!n.isSubflowRoot
|
|
2399
|
+
};
|
|
2400
|
+
if (n.isSubflowRoot && n.subflowStructure) {
|
|
2401
|
+
entry.children = specToTree(n.subflowStructure);
|
|
2402
|
+
}
|
|
2403
|
+
entries.push(entry);
|
|
2404
|
+
if (n.children) {
|
|
2405
|
+
for (const child of n.children) {
|
|
2406
|
+
walk(child);
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
if (n.next) {
|
|
2410
|
+
walk(n.next);
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
walk(node);
|
|
2414
|
+
return entries;
|
|
2415
|
+
}
|
|
2416
|
+
var TreeNode = (0, import_react11.memo)(function TreeNode2({
|
|
2417
|
+
entry,
|
|
2418
|
+
depth,
|
|
2419
|
+
activeStage,
|
|
2420
|
+
doneStages,
|
|
2421
|
+
onNodeSelect
|
|
2422
|
+
}) {
|
|
2423
|
+
const [expanded, setExpanded] = (0, import_react11.useState)(true);
|
|
2424
|
+
const hasChildren = entry.children && entry.children.length > 0;
|
|
2425
|
+
const isActive = activeStage === entry.name;
|
|
2426
|
+
const isDone = doneStages?.has(entry.name);
|
|
2427
|
+
const handleClick = (0, import_react11.useCallback)(() => {
|
|
2428
|
+
if (hasChildren) {
|
|
2429
|
+
setExpanded((prev) => !prev);
|
|
2430
|
+
}
|
|
2431
|
+
onNodeSelect?.(entry.name, !!entry.isSubflow);
|
|
2432
|
+
}, [hasChildren, onNodeSelect, entry.name, entry.isSubflow]);
|
|
2433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
2434
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2435
|
+
"button",
|
|
2436
|
+
{
|
|
2437
|
+
onClick: handleClick,
|
|
2438
|
+
"data-fp": "subflow-tree-node",
|
|
2439
|
+
style: {
|
|
2440
|
+
display: "flex",
|
|
2441
|
+
alignItems: "center",
|
|
2442
|
+
gap: 6,
|
|
2443
|
+
width: "100%",
|
|
2444
|
+
border: "none",
|
|
2445
|
+
background: isActive ? `color-mix(in srgb, ${theme.primary} 15%, transparent)` : "transparent",
|
|
2446
|
+
cursor: "pointer",
|
|
2447
|
+
padding: `4px 8px 4px ${8 + depth * 16}px`,
|
|
2448
|
+
fontFamily: theme.fontSans,
|
|
2449
|
+
fontSize: 12,
|
|
2450
|
+
textAlign: "left",
|
|
2451
|
+
borderRadius: 4,
|
|
2452
|
+
transition: "background 0.15s"
|
|
2453
|
+
},
|
|
2454
|
+
onMouseEnter: (e) => {
|
|
2455
|
+
if (!isActive) {
|
|
2456
|
+
e.currentTarget.style.background = `color-mix(in srgb, ${theme.textMuted} 10%, transparent)`;
|
|
2457
|
+
}
|
|
2458
|
+
},
|
|
2459
|
+
onMouseLeave: (e) => {
|
|
2460
|
+
if (!isActive) {
|
|
2461
|
+
e.currentTarget.style.background = "transparent";
|
|
2462
|
+
}
|
|
2463
|
+
},
|
|
2464
|
+
children: [
|
|
2465
|
+
hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2466
|
+
"span",
|
|
2467
|
+
{
|
|
2468
|
+
style: {
|
|
2469
|
+
fontSize: 10,
|
|
2470
|
+
color: theme.textMuted,
|
|
2471
|
+
width: 12,
|
|
2472
|
+
textAlign: "center",
|
|
2473
|
+
flexShrink: 0,
|
|
2474
|
+
transition: "transform 0.15s",
|
|
2475
|
+
transform: expanded ? "rotate(90deg)" : "rotate(0deg)",
|
|
2476
|
+
display: "inline-block"
|
|
2477
|
+
},
|
|
2478
|
+
children: "\u25B6"
|
|
2479
|
+
}
|
|
2480
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { width: 12, flexShrink: 0 } }),
|
|
2481
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2482
|
+
"span",
|
|
2483
|
+
{
|
|
2484
|
+
style: {
|
|
2485
|
+
width: 6,
|
|
2486
|
+
height: 6,
|
|
2487
|
+
borderRadius: "50%",
|
|
2488
|
+
flexShrink: 0,
|
|
2489
|
+
background: isActive ? theme.primary : isDone ? theme.success : theme.border
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
),
|
|
2493
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
|
|
2494
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2495
|
+
"span",
|
|
2496
|
+
{
|
|
2497
|
+
style: {
|
|
2498
|
+
color: isActive ? theme.primary : isDone ? theme.textPrimary : theme.textSecondary,
|
|
2499
|
+
fontWeight: isActive ? 600 : entry.isSubflow ? 500 : 400,
|
|
2500
|
+
whiteSpace: "nowrap",
|
|
2501
|
+
overflow: "hidden",
|
|
2502
|
+
textOverflow: "ellipsis"
|
|
2503
|
+
},
|
|
2504
|
+
children: [
|
|
2505
|
+
entry.name,
|
|
2506
|
+
entry.isSubflow && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { opacity: 0.5, marginLeft: 4, fontSize: 10 }, children: "\u229E" })
|
|
2507
|
+
]
|
|
2508
|
+
}
|
|
2509
|
+
),
|
|
2510
|
+
entry.description && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2511
|
+
"span",
|
|
2512
|
+
{
|
|
2513
|
+
style: {
|
|
2514
|
+
color: theme.textMuted,
|
|
2515
|
+
fontSize: 10,
|
|
2516
|
+
whiteSpace: "nowrap",
|
|
2517
|
+
overflow: "hidden",
|
|
2518
|
+
textOverflow: "ellipsis"
|
|
2519
|
+
},
|
|
2520
|
+
children: entry.description
|
|
2521
|
+
}
|
|
2522
|
+
)
|
|
2523
|
+
] })
|
|
2524
|
+
]
|
|
2525
|
+
}
|
|
2526
|
+
),
|
|
2527
|
+
hasChildren && expanded && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: entry.children.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2528
|
+
TreeNode2,
|
|
2529
|
+
{
|
|
2530
|
+
entry: child,
|
|
2531
|
+
depth: depth + 1,
|
|
2532
|
+
activeStage,
|
|
2533
|
+
doneStages,
|
|
2534
|
+
onNodeSelect
|
|
2535
|
+
},
|
|
2536
|
+
`${child.name}-${i}`
|
|
2537
|
+
)) })
|
|
2538
|
+
] });
|
|
2539
|
+
});
|
|
2540
|
+
var SectionLabel = (0, import_react11.memo)(function SectionLabel2({ children }) {
|
|
2541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2542
|
+
"div",
|
|
2543
|
+
{
|
|
2544
|
+
style: {
|
|
2545
|
+
padding: "4px 12px 8px",
|
|
2546
|
+
fontSize: 10,
|
|
2547
|
+
fontWeight: 600,
|
|
2548
|
+
textTransform: "uppercase",
|
|
2549
|
+
letterSpacing: "0.05em",
|
|
2550
|
+
color: theme.textMuted
|
|
2551
|
+
},
|
|
2552
|
+
children
|
|
2553
|
+
}
|
|
2554
|
+
);
|
|
2555
|
+
});
|
|
2556
|
+
var SubflowTree = (0, import_react11.memo)(function SubflowTree2({
|
|
2557
|
+
spec,
|
|
2558
|
+
activeStage,
|
|
2559
|
+
doneStages,
|
|
2560
|
+
onNodeSelect,
|
|
2561
|
+
unstyled = false,
|
|
2562
|
+
className,
|
|
2563
|
+
style
|
|
2564
|
+
}) {
|
|
2565
|
+
const tree = (0, import_react11.useMemo)(() => specToTree(spec), [spec]);
|
|
2566
|
+
const mainStages = (0, import_react11.useMemo)(() => tree.filter((e) => !e.isSubflow), [tree]);
|
|
2567
|
+
const subflowStages = (0, import_react11.useMemo)(() => tree.filter((e) => e.isSubflow), [tree]);
|
|
2568
|
+
const renderEntries = (entries) => entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2569
|
+
TreeNode,
|
|
2570
|
+
{
|
|
2571
|
+
entry,
|
|
2572
|
+
depth: 0,
|
|
2573
|
+
activeStage,
|
|
2574
|
+
doneStages,
|
|
2575
|
+
onNodeSelect
|
|
2576
|
+
},
|
|
2577
|
+
`${entry.name}-${i}`
|
|
2578
|
+
));
|
|
2579
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2580
|
+
"div",
|
|
2581
|
+
{
|
|
2582
|
+
className,
|
|
2583
|
+
"data-fp": "subflow-tree",
|
|
2584
|
+
style: {
|
|
2585
|
+
...unstyled ? {} : {
|
|
2586
|
+
fontFamily: theme.fontSans,
|
|
2587
|
+
fontSize: 12,
|
|
2588
|
+
background: theme.bgPrimary,
|
|
2589
|
+
borderRight: `1px solid ${theme.border}`,
|
|
2590
|
+
overflowY: "auto",
|
|
2591
|
+
overflowX: "hidden",
|
|
2592
|
+
padding: "8px 0"
|
|
2593
|
+
},
|
|
2594
|
+
...style
|
|
2595
|
+
},
|
|
2596
|
+
children: [
|
|
2597
|
+
!unstyled && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionLabel, { children: "Flowchart" }),
|
|
2598
|
+
renderEntries(mainStages),
|
|
2599
|
+
subflowStages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
2600
|
+
!unstyled && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { height: 1, background: theme.border, margin: "8px 12px" } }),
|
|
2601
|
+
!unstyled && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionLabel, { children: "Subflows" }),
|
|
2602
|
+
renderEntries(subflowStages)
|
|
2603
|
+
] })
|
|
2604
|
+
]
|
|
2605
|
+
}
|
|
2606
|
+
);
|
|
2607
|
+
});
|
|
2608
|
+
|
|
1851
2609
|
// src/adapters/fromRuntimeSnapshot.ts
|
|
1852
2610
|
function toVisualizationSnapshots(runtime) {
|
|
1853
2611
|
const snapshots = [];
|
|
1854
|
-
flattenTree(runtime.executionTree, snapshots, runtime.sharedState);
|
|
2612
|
+
flattenTree(runtime.executionTree, snapshots, runtime.sharedState, 0, runtime.subflowResults, {});
|
|
1855
2613
|
return snapshots;
|
|
1856
2614
|
}
|
|
1857
|
-
function flattenTree(node, out, sharedState, accumulatedMs = 0) {
|
|
2615
|
+
function flattenTree(node, out, sharedState, accumulatedMs = 0, subflowResults, cumulativeMemory = {}) {
|
|
1858
2616
|
const durationMs = typeof node.metrics?.durationMs === "number" ? node.metrics.durationMs : 1;
|
|
1859
2617
|
const startMs = accumulatedMs;
|
|
1860
2618
|
const narrative = buildNarrative(node);
|
|
1861
|
-
const memory = {};
|
|
1862
|
-
if (node.
|
|
1863
|
-
Object.
|
|
2619
|
+
const memory = { ...cumulativeMemory };
|
|
2620
|
+
if (node.stageWrites) {
|
|
2621
|
+
for (const [key, value] of Object.entries(node.stageWrites)) {
|
|
2622
|
+
if (value === void 0) {
|
|
2623
|
+
delete memory[key];
|
|
2624
|
+
} else {
|
|
2625
|
+
memory[key] = value;
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
1864
2628
|
}
|
|
2629
|
+
const stageId = node.name || node.id;
|
|
2630
|
+
const sfResult = subflowResults?.[node.subflowId ?? stageId];
|
|
1865
2631
|
out.push({
|
|
1866
|
-
stageName:
|
|
1867
|
-
stageLabel:
|
|
2632
|
+
stageName: stageId,
|
|
2633
|
+
stageLabel: stageId,
|
|
1868
2634
|
memory,
|
|
1869
2635
|
narrative,
|
|
1870
2636
|
startMs,
|
|
1871
2637
|
durationMs,
|
|
1872
|
-
status: "done"
|
|
2638
|
+
status: "done",
|
|
2639
|
+
...node.description ? { description: node.description } : void 0,
|
|
2640
|
+
...node.subflowId ? { subflowId: node.subflowId } : void 0,
|
|
2641
|
+
...sfResult ? { subflowResult: sfResult } : void 0
|
|
1873
2642
|
});
|
|
1874
2643
|
let nextMs = startMs + durationMs;
|
|
1875
2644
|
if (node.children && node.children.length > 0) {
|
|
1876
2645
|
let maxChildEnd = nextMs;
|
|
1877
2646
|
for (const child of node.children) {
|
|
1878
|
-
const childEnd = flattenTree(child, out, sharedState, nextMs);
|
|
2647
|
+
const childEnd = flattenTree(child, out, sharedState, nextMs, subflowResults, memory);
|
|
1879
2648
|
maxChildEnd = Math.max(maxChildEnd, childEnd);
|
|
1880
2649
|
}
|
|
1881
2650
|
nextMs = maxChildEnd;
|
|
1882
2651
|
}
|
|
1883
2652
|
if (node.next) {
|
|
1884
|
-
nextMs = flattenTree(node.next, out, sharedState, nextMs);
|
|
2653
|
+
nextMs = flattenTree(node.next, out, sharedState, nextMs, subflowResults, memory);
|
|
1885
2654
|
}
|
|
1886
2655
|
return nextMs;
|
|
1887
2656
|
}
|
|
@@ -1890,8 +2659,8 @@ function buildNarrative(node) {
|
|
|
1890
2659
|
if (node.name) {
|
|
1891
2660
|
parts.push(`Stage "${node.name}" executed.`);
|
|
1892
2661
|
}
|
|
1893
|
-
if (node.
|
|
1894
|
-
const keys = Object.keys(node.
|
|
2662
|
+
if (node.stageWrites && Object.keys(node.stageWrites).length > 0) {
|
|
2663
|
+
const keys = Object.keys(node.stageWrites);
|
|
1895
2664
|
parts.push(`Wrote ${keys.length} key(s): ${keys.join(", ")}.`);
|
|
1896
2665
|
}
|
|
1897
2666
|
if (node.errors && Object.keys(node.errors).length > 0) {
|
|
@@ -1915,7 +2684,9 @@ function createSnapshots(stages) {
|
|
|
1915
2684
|
narrative: s.narrative ?? `${s.label ?? s.name} completed.`,
|
|
1916
2685
|
startMs: accMs,
|
|
1917
2686
|
durationMs: duration,
|
|
1918
|
-
status: "done"
|
|
2687
|
+
status: "done",
|
|
2688
|
+
...s.description ? { description: s.description } : void 0,
|
|
2689
|
+
...s.subflowId ? { subflowId: s.subflowId } : void 0
|
|
1919
2690
|
};
|
|
1920
2691
|
accMs += duration;
|
|
1921
2692
|
return snap;
|
|
@@ -1932,6 +2703,8 @@ function createSnapshots(stages) {
|
|
|
1932
2703
|
ResultPanel,
|
|
1933
2704
|
ScopeDiff,
|
|
1934
2705
|
SnapshotPanel,
|
|
2706
|
+
StageDetailPanel,
|
|
2707
|
+
SubflowTree,
|
|
1935
2708
|
TimeTravelControls,
|
|
1936
2709
|
coolDark,
|
|
1937
2710
|
createSnapshots,
|