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.
Files changed (161) hide show
  1. package/README.md +42 -3
  2. package/dist/adapters/fromRuntimeSnapshot.d.ts +52 -0
  3. package/dist/adapters/fromRuntimeSnapshot.d.ts.map +1 -0
  4. package/dist/adapters/fromRuntimeSnapshot.js +97 -0
  5. package/dist/adapters/fromRuntimeSnapshot.js.map +1 -0
  6. package/dist/components/ExplainableShell/ExplainableShell.d.ts +26 -0
  7. package/dist/components/ExplainableShell/ExplainableShell.d.ts.map +1 -0
  8. package/dist/components/ExplainableShell/ExplainableShell.js +94 -0
  9. package/dist/components/ExplainableShell/ExplainableShell.js.map +1 -0
  10. package/dist/components/ExplainableShell/index.d.ts +3 -0
  11. package/dist/components/ExplainableShell/index.d.ts.map +1 -0
  12. package/dist/components/ExplainableShell/index.js +2 -0
  13. package/dist/components/ExplainableShell/index.js.map +1 -0
  14. package/dist/components/FlowchartView/FlowchartView.d.ts +20 -0
  15. package/dist/components/FlowchartView/FlowchartView.d.ts.map +1 -0
  16. package/dist/components/FlowchartView/FlowchartView.js +80 -0
  17. package/dist/components/FlowchartView/FlowchartView.js.map +1 -0
  18. package/dist/components/FlowchartView/SubflowBreadcrumb.d.ts +11 -0
  19. package/dist/components/FlowchartView/SubflowBreadcrumb.d.ts.map +1 -0
  20. package/dist/components/FlowchartView/SubflowBreadcrumb.js +49 -0
  21. package/dist/components/FlowchartView/SubflowBreadcrumb.js.map +1 -0
  22. package/dist/components/FlowchartView/SubflowTree.d.ts +36 -0
  23. package/dist/components/FlowchartView/SubflowTree.d.ts.map +1 -0
  24. package/dist/components/FlowchartView/SubflowTree.js +143 -0
  25. package/dist/components/FlowchartView/SubflowTree.js.map +1 -0
  26. package/dist/components/FlowchartView/TracedFlowchartView.d.ts +20 -0
  27. package/dist/components/FlowchartView/TracedFlowchartView.d.ts.map +1 -0
  28. package/dist/components/FlowchartView/TracedFlowchartView.js +101 -0
  29. package/dist/components/FlowchartView/TracedFlowchartView.js.map +1 -0
  30. package/dist/components/FlowchartView/index.d.ts +11 -0
  31. package/dist/components/FlowchartView/index.d.ts.map +1 -0
  32. package/dist/components/FlowchartView/index.js +6 -0
  33. package/dist/components/FlowchartView/index.js.map +1 -0
  34. package/dist/components/FlowchartView/specToReactFlow.d.ts +56 -0
  35. package/dist/components/FlowchartView/specToReactFlow.d.ts.map +1 -0
  36. package/dist/components/FlowchartView/specToReactFlow.js +202 -0
  37. package/dist/components/FlowchartView/specToReactFlow.js.map +1 -0
  38. package/dist/components/FlowchartView/useSubflowNavigation.d.ts +35 -0
  39. package/dist/components/FlowchartView/useSubflowNavigation.d.ts.map +1 -0
  40. package/dist/components/FlowchartView/useSubflowNavigation.js +80 -0
  41. package/dist/components/FlowchartView/useSubflowNavigation.js.map +1 -0
  42. package/dist/components/GanttTimeline/GanttTimeline.d.ts +18 -0
  43. package/dist/components/GanttTimeline/GanttTimeline.d.ts.map +1 -0
  44. package/dist/components/GanttTimeline/GanttTimeline.js +123 -0
  45. package/dist/components/GanttTimeline/GanttTimeline.js.map +1 -0
  46. package/dist/components/GanttTimeline/index.d.ts +3 -0
  47. package/dist/components/GanttTimeline/index.d.ts.map +1 -0
  48. package/dist/components/GanttTimeline/index.js +2 -0
  49. package/dist/components/GanttTimeline/index.js.map +1 -0
  50. package/dist/components/MemoryInspector/MemoryInspector.d.ts +19 -0
  51. package/dist/components/MemoryInspector/MemoryInspector.d.ts.map +1 -0
  52. package/dist/components/MemoryInspector/MemoryInspector.js +95 -0
  53. package/dist/components/MemoryInspector/MemoryInspector.js.map +1 -0
  54. package/dist/components/MemoryInspector/index.d.ts +3 -0
  55. package/dist/components/MemoryInspector/index.d.ts.map +1 -0
  56. package/dist/components/MemoryInspector/index.js +2 -0
  57. package/dist/components/MemoryInspector/index.js.map +1 -0
  58. package/dist/components/NarrativeLog/NarrativeLog.d.ts +15 -0
  59. package/dist/components/NarrativeLog/NarrativeLog.d.ts.map +1 -0
  60. package/dist/components/NarrativeLog/NarrativeLog.js +65 -0
  61. package/dist/components/NarrativeLog/NarrativeLog.js.map +1 -0
  62. package/dist/components/NarrativeLog/index.d.ts +3 -0
  63. package/dist/components/NarrativeLog/index.d.ts.map +1 -0
  64. package/dist/components/NarrativeLog/index.js +2 -0
  65. package/dist/components/NarrativeLog/index.js.map +1 -0
  66. package/dist/components/NarrativeTrace/NarrativeTrace.d.ts +13 -0
  67. package/dist/components/NarrativeTrace/NarrativeTrace.d.ts.map +1 -0
  68. package/dist/components/NarrativeTrace/NarrativeTrace.js +127 -0
  69. package/dist/components/NarrativeTrace/NarrativeTrace.js.map +1 -0
  70. package/dist/components/NarrativeTrace/index.d.ts +3 -0
  71. package/dist/components/NarrativeTrace/index.d.ts.map +1 -0
  72. package/dist/components/NarrativeTrace/index.js +2 -0
  73. package/dist/components/NarrativeTrace/index.js.map +1 -0
  74. package/dist/components/ResultPanel/ResultPanel.d.ts +11 -0
  75. package/dist/components/ResultPanel/ResultPanel.d.ts.map +1 -0
  76. package/dist/components/ResultPanel/ResultPanel.js +54 -0
  77. package/dist/components/ResultPanel/ResultPanel.js.map +1 -0
  78. package/dist/components/ResultPanel/index.d.ts +3 -0
  79. package/dist/components/ResultPanel/index.d.ts.map +1 -0
  80. package/dist/components/ResultPanel/index.js +2 -0
  81. package/dist/components/ResultPanel/index.js.map +1 -0
  82. package/dist/components/ScopeDiff/ScopeDiff.d.ts +17 -0
  83. package/dist/components/ScopeDiff/ScopeDiff.d.ts.map +1 -0
  84. package/dist/components/ScopeDiff/ScopeDiff.js +87 -0
  85. package/dist/components/ScopeDiff/ScopeDiff.js.map +1 -0
  86. package/dist/components/ScopeDiff/index.d.ts +3 -0
  87. package/dist/components/ScopeDiff/index.d.ts.map +1 -0
  88. package/dist/components/ScopeDiff/index.js +2 -0
  89. package/dist/components/ScopeDiff/index.js.map +1 -0
  90. package/dist/components/SnapshotPanel/SnapshotPanel.d.ts +17 -0
  91. package/dist/components/SnapshotPanel/SnapshotPanel.d.ts.map +1 -0
  92. package/dist/components/SnapshotPanel/SnapshotPanel.js +85 -0
  93. package/dist/components/SnapshotPanel/SnapshotPanel.js.map +1 -0
  94. package/dist/components/SnapshotPanel/index.d.ts +3 -0
  95. package/dist/components/SnapshotPanel/index.d.ts.map +1 -0
  96. package/dist/components/SnapshotPanel/index.js +2 -0
  97. package/dist/components/SnapshotPanel/index.js.map +1 -0
  98. package/dist/components/StageNode/StageNode.d.ts +31 -0
  99. package/dist/components/StageNode/StageNode.d.ts.map +1 -0
  100. package/dist/components/StageNode/StageNode.js +134 -0
  101. package/dist/components/StageNode/StageNode.js.map +1 -0
  102. package/dist/components/StageNode/index.d.ts +3 -0
  103. package/dist/components/StageNode/index.d.ts.map +1 -0
  104. package/dist/components/StageNode/index.js +2 -0
  105. package/dist/components/StageNode/index.js.map +1 -0
  106. package/dist/components/TimeTravelControls/TimeTravelControls.d.ts +13 -0
  107. package/dist/components/TimeTravelControls/TimeTravelControls.d.ts.map +1 -0
  108. package/dist/components/TimeTravelControls/TimeTravelControls.js +104 -0
  109. package/dist/components/TimeTravelControls/TimeTravelControls.js.map +1 -0
  110. package/dist/components/TimeTravelControls/index.d.ts +3 -0
  111. package/dist/components/TimeTravelControls/index.d.ts.map +1 -0
  112. package/dist/components/TimeTravelControls/index.js +2 -0
  113. package/dist/components/TimeTravelControls/index.js.map +1 -0
  114. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts +22 -0
  115. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts.map +1 -0
  116. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js +104 -0
  117. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js.map +1 -0
  118. package/dist/components/TimeTravelDebugger/index.d.ts +3 -0
  119. package/dist/components/TimeTravelDebugger/index.d.ts.map +1 -0
  120. package/dist/components/TimeTravelDebugger/index.js +2 -0
  121. package/dist/components/TimeTravelDebugger/index.js.map +1 -0
  122. package/dist/flowchart.cjs +704 -220
  123. package/dist/flowchart.cjs.map +1 -1
  124. package/dist/flowchart.d.cts +55 -1
  125. package/dist/flowchart.d.ts +55 -1
  126. package/dist/flowchart.d.ts.map +1 -0
  127. package/dist/flowchart.js +700 -214
  128. package/dist/flowchart.js.map +1 -1
  129. package/dist/index.cjs +849 -76
  130. package/dist/index.cjs.map +1 -1
  131. package/dist/index.d.cts +95 -3
  132. package/dist/index.d.ts +95 -3
  133. package/dist/index.d.ts.map +1 -0
  134. package/dist/index.js +851 -80
  135. package/dist/index.js.map +1 -1
  136. package/dist/theme/ThemeProvider.d.ts +13 -0
  137. package/dist/theme/ThemeProvider.d.ts.map +1 -0
  138. package/dist/theme/ThemeProvider.js +16 -0
  139. package/dist/theme/ThemeProvider.js.map +1 -0
  140. package/dist/theme/index.d.ts +7 -0
  141. package/dist/theme/index.d.ts.map +1 -0
  142. package/dist/theme/index.js +5 -0
  143. package/dist/theme/index.js.map +1 -0
  144. package/dist/theme/presets.d.ts +15 -0
  145. package/dist/theme/presets.d.ts.map +1 -0
  146. package/dist/theme/presets.js +70 -0
  147. package/dist/theme/presets.js.map +1 -0
  148. package/dist/theme/styles.d.ts +32 -0
  149. package/dist/theme/styles.d.ts.map +1 -0
  150. package/dist/theme/styles.js +37 -0
  151. package/dist/theme/styles.js.map +1 -0
  152. package/dist/theme/tokens.d.ts +28 -0
  153. package/dist/theme/tokens.d.ts.map +1 -0
  154. package/dist/theme/tokens.js +58 -0
  155. package/dist/theme/tokens.js.map +1 -0
  156. package/dist/tsconfig.tsbuildinfo +1 -0
  157. package/dist/types.d.ts +35 -0
  158. package/dist/types.d.ts.map +1 -0
  159. package/dist/types.js +2 -0
  160. package/dist/types.js.map +1 -0
  161. package/package.json +10 -4
package/dist/flowchart.js CHANGED
@@ -77,7 +77,7 @@ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
77
77
  var StageNode = memo(function StageNode2({
78
78
  data
79
79
  }) {
80
- const { label, active, done, error, linked, stepNumbers, dimmed, isSubflow } = data;
80
+ const { label, active, done, error, linked, stepNumbers, dimmed, isSubflow, description } = data;
81
81
  const isOnPath = active || done;
82
82
  const bg = active ? theme.primary : done ? theme.success : error ? theme.error : theme.bgSecondary;
83
83
  const borderColor = active ? theme.primary : done ? theme.success : error ? theme.error : theme.border;
@@ -166,10 +166,11 @@ var StageNode = memo(function StageNode2({
166
166
  background: bg,
167
167
  border: `2px solid ${borderColor}`,
168
168
  borderRadius: theme.radius,
169
- padding: "10px 20px",
169
+ padding: description ? "8px 16px" : "10px 20px",
170
170
  display: "flex",
171
+ flexDirection: "column",
171
172
  alignItems: "center",
172
- gap: 6,
173
+ gap: description ? 2 : 0,
173
174
  boxShadow: shadow,
174
175
  transition: "all 0.3s ease",
175
176
  fontFamily: theme.fontSans,
@@ -177,59 +178,77 @@ var StageNode = memo(function StageNode2({
177
178
  justifyContent: "center"
178
179
  },
179
180
  children: [
180
- done && /* @__PURE__ */ jsx2("span", { style: { fontSize: 10, color: textColor }, children: "\u2713" }),
181
- active && /* @__PURE__ */ jsx2(
182
- "span",
183
- {
184
- style: {
185
- width: 8,
186
- height: 8,
187
- borderRadius: "50%",
188
- background: "#fff",
189
- animation: "fp-blink 1s ease-in-out infinite",
190
- flexShrink: 0
181
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
182
+ done && /* @__PURE__ */ jsx2("span", { style: { fontSize: 10, color: textColor }, children: "\u2713" }),
183
+ active && /* @__PURE__ */ jsx2(
184
+ "span",
185
+ {
186
+ style: {
187
+ width: 8,
188
+ height: 8,
189
+ borderRadius: "50%",
190
+ background: "#fff",
191
+ animation: "fp-blink 1s ease-in-out infinite",
192
+ flexShrink: 0
193
+ }
191
194
  }
192
- }
193
- ),
194
- error && /* @__PURE__ */ jsx2("span", { style: { fontSize: 10, color: textColor }, children: "\u2717" }),
195
- /* @__PURE__ */ jsx2(
195
+ ),
196
+ error && /* @__PURE__ */ jsx2("span", { style: { fontSize: 10, color: textColor }, children: "\u2717" }),
197
+ /* @__PURE__ */ jsx2(
198
+ "span",
199
+ {
200
+ style: {
201
+ fontSize: 13,
202
+ fontWeight: 500,
203
+ color: textColor,
204
+ whiteSpace: "nowrap"
205
+ },
206
+ children: label
207
+ }
208
+ ),
209
+ isSubflow && /* @__PURE__ */ jsx2(
210
+ "span",
211
+ {
212
+ style: {
213
+ display: "inline-flex",
214
+ alignItems: "center",
215
+ justifyContent: "center",
216
+ width: 16,
217
+ height: 16,
218
+ borderRadius: 3,
219
+ border: `1.5px solid ${textColor}`,
220
+ position: "relative",
221
+ opacity: 0.7,
222
+ flexShrink: 0
223
+ },
224
+ children: /* @__PURE__ */ jsx2(
225
+ "span",
226
+ {
227
+ style: {
228
+ width: 8,
229
+ height: 8,
230
+ borderRadius: 2,
231
+ border: `1px solid ${textColor}`
232
+ }
233
+ }
234
+ )
235
+ }
236
+ )
237
+ ] }),
238
+ description && /* @__PURE__ */ jsx2(
196
239
  "span",
197
240
  {
198
241
  style: {
199
- fontSize: 13,
200
- fontWeight: 500,
242
+ fontSize: 10,
243
+ fontWeight: 400,
201
244
  color: textColor,
202
- whiteSpace: "nowrap"
203
- },
204
- children: label
205
- }
206
- ),
207
- isSubflow && /* @__PURE__ */ jsx2(
208
- "span",
209
- {
210
- style: {
211
- display: "inline-flex",
212
- alignItems: "center",
213
- justifyContent: "center",
214
- width: 16,
215
- height: 16,
216
- borderRadius: 3,
217
- border: `1.5px solid ${textColor}`,
218
- position: "relative",
219
245
  opacity: 0.7,
220
- flexShrink: 0
246
+ whiteSpace: "nowrap",
247
+ overflow: "hidden",
248
+ textOverflow: "ellipsis",
249
+ maxWidth: 160
221
250
  },
222
- children: /* @__PURE__ */ jsx2(
223
- "span",
224
- {
225
- style: {
226
- width: 8,
227
- height: 8,
228
- borderRadius: 2,
229
- border: `1px solid ${textColor}`
230
- }
231
- }
232
- )
251
+ children: description
233
252
  }
234
253
  )
235
254
  ]
@@ -373,75 +392,13 @@ function FlowchartView({
373
392
  );
374
393
  }
375
394
 
376
- // src/components/FlowchartView/SubflowBreadcrumb.tsx
377
- import { memo as memo2 } from "react";
378
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
379
- var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
380
- breadcrumbs,
381
- onNavigate
382
- }) {
383
- if (breadcrumbs.length <= 1) return null;
384
- return /* @__PURE__ */ jsx4(
385
- "div",
386
- {
387
- style: {
388
- display: "flex",
389
- alignItems: "center",
390
- gap: 4,
391
- padding: "6px 12px",
392
- background: theme.bgSecondary,
393
- borderBottom: `1px solid ${theme.border}`,
394
- fontSize: 12,
395
- fontFamily: theme.fontSans,
396
- flexShrink: 0,
397
- overflowX: "auto"
398
- },
399
- children: breadcrumbs.map((crumb, i) => {
400
- const isLast = i === breadcrumbs.length - 1;
401
- return /* @__PURE__ */ jsxs2("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
402
- i > 0 && /* @__PURE__ */ jsx4("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" }),
403
- isLast ? /* @__PURE__ */ jsx4(
404
- "span",
405
- {
406
- style: {
407
- color: theme.primary,
408
- fontWeight: 600
409
- },
410
- children: crumb.label
411
- }
412
- ) : /* @__PURE__ */ jsx4(
413
- "button",
414
- {
415
- onClick: () => onNavigate(i),
416
- style: {
417
- background: "none",
418
- border: "none",
419
- color: theme.textSecondary,
420
- cursor: "pointer",
421
- padding: "2px 4px",
422
- borderRadius: 4,
423
- fontSize: 12,
424
- fontFamily: "inherit",
425
- fontWeight: 500,
426
- transition: "color 0.15s"
427
- },
428
- onMouseEnter: (e) => {
429
- e.currentTarget.style.color = `${theme.primary}`;
430
- },
431
- onMouseLeave: (e) => {
432
- e.currentTarget.style.color = `${theme.textSecondary}`;
433
- },
434
- children: crumb.label
435
- }
436
- )
437
- ] }, i);
438
- })
439
- }
440
- );
441
- });
442
-
443
- // src/components/FlowchartView/useSubflowNavigation.ts
444
- import { useState, useCallback as useCallback2, useMemo as useMemo2 } from "react";
395
+ // src/components/FlowchartView/TracedFlowchartView.tsx
396
+ import { useState as useState3, useMemo as useMemo4, useCallback as useCallback4 } from "react";
397
+ import {
398
+ ReactFlow as ReactFlow2,
399
+ Background as Background2,
400
+ BackgroundVariant as BackgroundVariant2
401
+ } from "@xyflow/react";
445
402
 
446
403
  // src/components/FlowchartView/specToReactFlow.ts
447
404
  var DEFAULT_COLORS = {
@@ -569,6 +526,7 @@ function walk(node, state, x, y) {
569
526
  isDecider,
570
527
  isFork,
571
528
  description: node.description,
529
+ subflowId: node.subflowId,
572
530
  dimmed,
573
531
  stepNumbers,
574
532
  isSubflow: !!node.isSubflowRoot
@@ -623,6 +581,7 @@ function specToReactFlow(spec, overlay, colors) {
623
581
  }
624
582
 
625
583
  // src/components/FlowchartView/useSubflowNavigation.ts
584
+ import { useState, useCallback as useCallback2, useMemo as useMemo2 } from "react";
626
585
  function useSubflowNavigation(rootSpec, overlay, colors) {
627
586
  const [stack, setStack] = useState([]);
628
587
  const currentSpec = stack.length > 0 ? stack[stack.length - 1].spec : rootSpec;
@@ -646,8 +605,9 @@ function useSubflowNavigation(rootSpec, overlay, colors) {
646
605
  }, [currentSpec]);
647
606
  const breadcrumbs = useMemo2(() => {
648
607
  const root = {
649
- label: rootSpec?.name || "Pipeline",
650
- spec: rootSpec
608
+ label: rootSpec?.name || "Flowchart",
609
+ spec: rootSpec,
610
+ description: rootSpec?.description
651
611
  };
652
612
  return [root, ...stack];
653
613
  }, [rootSpec, stack]);
@@ -659,7 +619,8 @@ function useSubflowNavigation(rootSpec, overlay, colors) {
659
619
  ...prev,
660
620
  {
661
621
  label: subflowNode.subflowName || subflowNode.name,
662
- spec: subflowNode.subflowStructure
622
+ spec: subflowNode.subflowStructure,
623
+ description: subflowNode.description
663
624
  }
664
625
  ]);
665
626
  return true;
@@ -683,16 +644,486 @@ function useSubflowNavigation(rootSpec, overlay, colors) {
683
644
  handleNodeClick,
684
645
  navigateTo,
685
646
  isInSubflow: stack.length > 0,
686
- currentSubflowNodeName: stack.length > 0 ? stack[0].label : null
647
+ currentSubflowNodeName: stack.length > 0 ? stack[stack.length - 1].label : null
687
648
  };
688
649
  }
689
650
 
651
+ // src/components/FlowchartView/SubflowBreadcrumb.tsx
652
+ import { memo as memo2 } from "react";
653
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
654
+ var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
655
+ breadcrumbs,
656
+ onNavigate
657
+ }) {
658
+ if (breadcrumbs.length <= 1) return null;
659
+ return /* @__PURE__ */ jsx4(
660
+ "div",
661
+ {
662
+ style: {
663
+ display: "flex",
664
+ alignItems: "center",
665
+ gap: 4,
666
+ padding: "6px 12px",
667
+ background: theme.bgSecondary,
668
+ borderBottom: `1px solid ${theme.border}`,
669
+ fontSize: 12,
670
+ fontFamily: theme.fontSans,
671
+ flexShrink: 0,
672
+ overflowX: "auto"
673
+ },
674
+ children: breadcrumbs.map((crumb, i) => {
675
+ const isLast = i === breadcrumbs.length - 1;
676
+ return /* @__PURE__ */ jsxs2("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
677
+ i > 0 && /* @__PURE__ */ jsx4("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" }),
678
+ isLast ? /* @__PURE__ */ jsxs2("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
679
+ /* @__PURE__ */ jsx4(
680
+ "span",
681
+ {
682
+ style: {
683
+ color: theme.primary,
684
+ fontWeight: 600
685
+ },
686
+ children: crumb.label
687
+ }
688
+ ),
689
+ crumb.description && /* @__PURE__ */ jsxs2(
690
+ "span",
691
+ {
692
+ style: {
693
+ color: theme.textMuted,
694
+ fontWeight: 400,
695
+ fontSize: 11
696
+ },
697
+ children: [
698
+ "\u2014 ",
699
+ crumb.description
700
+ ]
701
+ }
702
+ )
703
+ ] }) : /* @__PURE__ */ jsx4(
704
+ "button",
705
+ {
706
+ onClick: () => onNavigate(i),
707
+ style: {
708
+ background: "none",
709
+ border: "none",
710
+ color: theme.textSecondary,
711
+ cursor: "pointer",
712
+ padding: "2px 4px",
713
+ borderRadius: 4,
714
+ fontSize: 12,
715
+ fontFamily: "inherit",
716
+ fontWeight: 500,
717
+ transition: "color 0.15s"
718
+ },
719
+ onMouseEnter: (e) => {
720
+ e.currentTarget.style.color = `${theme.primary}`;
721
+ },
722
+ onMouseLeave: (e) => {
723
+ e.currentTarget.style.color = `${theme.textSecondary}`;
724
+ },
725
+ children: crumb.label
726
+ }
727
+ )
728
+ ] }, `${crumb.label}-${i}`);
729
+ })
730
+ }
731
+ );
732
+ });
733
+
734
+ // src/components/FlowchartView/SubflowTree.tsx
735
+ import { memo as memo3, useState as useState2, useCallback as useCallback3, useMemo as useMemo3 } from "react";
736
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
737
+ function specToTree(node) {
738
+ const entries = [];
739
+ const seen = /* @__PURE__ */ new Set();
740
+ function walk2(n) {
741
+ const id = n.name || n.id || "";
742
+ if (seen.has(id)) return;
743
+ seen.add(id);
744
+ const entry = {
745
+ name: n.name,
746
+ description: n.description,
747
+ subflowId: n.subflowId,
748
+ isSubflow: !!n.isSubflowRoot
749
+ };
750
+ if (n.isSubflowRoot && n.subflowStructure) {
751
+ entry.children = specToTree(n.subflowStructure);
752
+ }
753
+ entries.push(entry);
754
+ if (n.children) {
755
+ for (const child of n.children) {
756
+ walk2(child);
757
+ }
758
+ }
759
+ if (n.next) {
760
+ walk2(n.next);
761
+ }
762
+ }
763
+ walk2(node);
764
+ return entries;
765
+ }
766
+ var TreeNode = memo3(function TreeNode2({
767
+ entry,
768
+ depth,
769
+ activeStage,
770
+ doneStages,
771
+ onNodeSelect
772
+ }) {
773
+ const [expanded, setExpanded] = useState2(true);
774
+ const hasChildren = entry.children && entry.children.length > 0;
775
+ const isActive = activeStage === entry.name;
776
+ const isDone = doneStages?.has(entry.name);
777
+ const handleClick = useCallback3(() => {
778
+ if (hasChildren) {
779
+ setExpanded((prev) => !prev);
780
+ }
781
+ onNodeSelect?.(entry.name, !!entry.isSubflow);
782
+ }, [hasChildren, onNodeSelect, entry.name, entry.isSubflow]);
783
+ return /* @__PURE__ */ jsxs3(Fragment2, { children: [
784
+ /* @__PURE__ */ jsxs3(
785
+ "button",
786
+ {
787
+ onClick: handleClick,
788
+ "data-fp": "subflow-tree-node",
789
+ style: {
790
+ display: "flex",
791
+ alignItems: "center",
792
+ gap: 6,
793
+ width: "100%",
794
+ border: "none",
795
+ background: isActive ? `color-mix(in srgb, ${theme.primary} 15%, transparent)` : "transparent",
796
+ cursor: "pointer",
797
+ padding: `4px 8px 4px ${8 + depth * 16}px`,
798
+ fontFamily: theme.fontSans,
799
+ fontSize: 12,
800
+ textAlign: "left",
801
+ borderRadius: 4,
802
+ transition: "background 0.15s"
803
+ },
804
+ onMouseEnter: (e) => {
805
+ if (!isActive) {
806
+ e.currentTarget.style.background = `color-mix(in srgb, ${theme.textMuted} 10%, transparent)`;
807
+ }
808
+ },
809
+ onMouseLeave: (e) => {
810
+ if (!isActive) {
811
+ e.currentTarget.style.background = "transparent";
812
+ }
813
+ },
814
+ children: [
815
+ hasChildren ? /* @__PURE__ */ jsx5(
816
+ "span",
817
+ {
818
+ style: {
819
+ fontSize: 10,
820
+ color: theme.textMuted,
821
+ width: 12,
822
+ textAlign: "center",
823
+ flexShrink: 0,
824
+ transition: "transform 0.15s",
825
+ transform: expanded ? "rotate(90deg)" : "rotate(0deg)",
826
+ display: "inline-block"
827
+ },
828
+ children: "\u25B6"
829
+ }
830
+ ) : /* @__PURE__ */ jsx5("span", { style: { width: 12, flexShrink: 0 } }),
831
+ /* @__PURE__ */ jsx5(
832
+ "span",
833
+ {
834
+ style: {
835
+ width: 6,
836
+ height: 6,
837
+ borderRadius: "50%",
838
+ flexShrink: 0,
839
+ background: isActive ? theme.primary : isDone ? theme.success : theme.border
840
+ }
841
+ }
842
+ ),
843
+ /* @__PURE__ */ jsxs3("span", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
844
+ /* @__PURE__ */ jsxs3(
845
+ "span",
846
+ {
847
+ style: {
848
+ color: isActive ? theme.primary : isDone ? theme.textPrimary : theme.textSecondary,
849
+ fontWeight: isActive ? 600 : entry.isSubflow ? 500 : 400,
850
+ whiteSpace: "nowrap",
851
+ overflow: "hidden",
852
+ textOverflow: "ellipsis"
853
+ },
854
+ children: [
855
+ entry.name,
856
+ entry.isSubflow && /* @__PURE__ */ jsx5("span", { style: { opacity: 0.5, marginLeft: 4, fontSize: 10 }, children: "\u229E" })
857
+ ]
858
+ }
859
+ ),
860
+ entry.description && /* @__PURE__ */ jsx5(
861
+ "span",
862
+ {
863
+ style: {
864
+ color: theme.textMuted,
865
+ fontSize: 10,
866
+ whiteSpace: "nowrap",
867
+ overflow: "hidden",
868
+ textOverflow: "ellipsis"
869
+ },
870
+ children: entry.description
871
+ }
872
+ )
873
+ ] })
874
+ ]
875
+ }
876
+ ),
877
+ hasChildren && expanded && /* @__PURE__ */ jsx5("div", { children: entry.children.map((child, i) => /* @__PURE__ */ jsx5(
878
+ TreeNode2,
879
+ {
880
+ entry: child,
881
+ depth: depth + 1,
882
+ activeStage,
883
+ doneStages,
884
+ onNodeSelect
885
+ },
886
+ `${child.name}-${i}`
887
+ )) })
888
+ ] });
889
+ });
890
+ var SectionLabel = memo3(function SectionLabel2({ children }) {
891
+ return /* @__PURE__ */ jsx5(
892
+ "div",
893
+ {
894
+ style: {
895
+ padding: "4px 12px 8px",
896
+ fontSize: 10,
897
+ fontWeight: 600,
898
+ textTransform: "uppercase",
899
+ letterSpacing: "0.05em",
900
+ color: theme.textMuted
901
+ },
902
+ children
903
+ }
904
+ );
905
+ });
906
+ var SubflowTree = memo3(function SubflowTree2({
907
+ spec,
908
+ activeStage,
909
+ doneStages,
910
+ onNodeSelect,
911
+ unstyled = false,
912
+ className,
913
+ style
914
+ }) {
915
+ const tree = useMemo3(() => specToTree(spec), [spec]);
916
+ const mainStages = useMemo3(() => tree.filter((e) => !e.isSubflow), [tree]);
917
+ const subflowStages = useMemo3(() => tree.filter((e) => e.isSubflow), [tree]);
918
+ const renderEntries = (entries) => entries.map((entry, i) => /* @__PURE__ */ jsx5(
919
+ TreeNode,
920
+ {
921
+ entry,
922
+ depth: 0,
923
+ activeStage,
924
+ doneStages,
925
+ onNodeSelect
926
+ },
927
+ `${entry.name}-${i}`
928
+ ));
929
+ return /* @__PURE__ */ jsxs3(
930
+ "div",
931
+ {
932
+ className,
933
+ "data-fp": "subflow-tree",
934
+ style: {
935
+ ...unstyled ? {} : {
936
+ fontFamily: theme.fontSans,
937
+ fontSize: 12,
938
+ background: theme.bgPrimary,
939
+ borderRight: `1px solid ${theme.border}`,
940
+ overflowY: "auto",
941
+ overflowX: "hidden",
942
+ padding: "8px 0"
943
+ },
944
+ ...style
945
+ },
946
+ children: [
947
+ !unstyled && /* @__PURE__ */ jsx5(SectionLabel, { children: "Flowchart" }),
948
+ renderEntries(mainStages),
949
+ subflowStages.length > 0 && /* @__PURE__ */ jsxs3(Fragment2, { children: [
950
+ !unstyled && /* @__PURE__ */ jsx5("div", { style: { height: 1, background: theme.border, margin: "8px 12px" } }),
951
+ !unstyled && /* @__PURE__ */ jsx5(SectionLabel, { children: "Subflows" }),
952
+ renderEntries(subflowStages)
953
+ ] })
954
+ ]
955
+ }
956
+ );
957
+ });
958
+
959
+ // src/components/FlowchartView/TracedFlowchartView.tsx
960
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
961
+ var nodeTypes2 = { stage: StageNode };
962
+ function TracedFlowchartView({
963
+ spec,
964
+ snapshots,
965
+ snapshotIndex = 0,
966
+ onNodeClick,
967
+ onSubflowChange,
968
+ showTree = false,
969
+ treeWidth = 200,
970
+ unstyled = false,
971
+ className,
972
+ style
973
+ }) {
974
+ const [treeVisible, setTreeVisible] = useState3(showTree);
975
+ const subflowNav = useSubflowNavigation(spec);
976
+ const currentSpec = subflowNav.breadcrumbs.length > 0 ? subflowNav.breadcrumbs[subflowNav.breadcrumbs.length - 1].spec : null;
977
+ const overlay = useMemo4(() => {
978
+ if (!snapshots || snapshots.length === 0) return void 0;
979
+ const executionOrder = snapshots.slice(0, snapshotIndex + 1).map((s) => s.stageLabel);
980
+ const doneStages = new Set(
981
+ snapshots.slice(0, snapshotIndex).map((s) => s.stageLabel)
982
+ );
983
+ const activeStage = snapshots[snapshotIndex]?.stageLabel ?? null;
984
+ const executedStages = /* @__PURE__ */ new Set([...doneStages]);
985
+ if (activeStage) executedStages.add(activeStage);
986
+ return { doneStages, activeStage, executedStages, executionOrder };
987
+ }, [snapshots, snapshotIndex]);
988
+ const { nodes, edges } = useMemo4(() => {
989
+ if (!currentSpec) return { nodes: [], edges: [] };
990
+ return specToReactFlow(currentSpec, overlay);
991
+ }, [currentSpec, overlay]);
992
+ const handleNodeClick = useCallback4(
993
+ (_, node) => {
994
+ if (subflowNav.handleNodeClick(node.id)) {
995
+ onSubflowChange?.(true, node.id);
996
+ return;
997
+ }
998
+ if (onNodeClick && snapshots) {
999
+ const idx = snapshots.findIndex((s) => s.stageLabel === node.id);
1000
+ if (idx >= 0) onNodeClick(idx);
1001
+ } else if (onNodeClick) {
1002
+ onNodeClick(node.id);
1003
+ }
1004
+ },
1005
+ [subflowNav, onNodeClick, onSubflowChange, snapshots]
1006
+ );
1007
+ const handleBreadcrumbNavigate = useCallback4(
1008
+ (level) => {
1009
+ subflowNav.navigateTo(level);
1010
+ onSubflowChange?.(level > 0, null);
1011
+ },
1012
+ [subflowNav, onSubflowChange]
1013
+ );
1014
+ const handleTreeNodeSelect = useCallback4(
1015
+ (name, isSubflow) => {
1016
+ if (isSubflow) {
1017
+ if (subflowNav.handleNodeClick(name)) {
1018
+ onSubflowChange?.(true, name);
1019
+ }
1020
+ } else if (onNodeClick && snapshots) {
1021
+ const idx = snapshots.findIndex((s) => s.stageLabel === name);
1022
+ if (idx >= 0) onNodeClick(idx);
1023
+ }
1024
+ },
1025
+ [subflowNav, onNodeClick, onSubflowChange, snapshots]
1026
+ );
1027
+ return /* @__PURE__ */ jsxs4(
1028
+ "div",
1029
+ {
1030
+ className,
1031
+ style: { width: "100%", height: "100%", display: "flex", flexDirection: "row", ...style },
1032
+ "data-fp": "traced-flowchart",
1033
+ children: [
1034
+ showTree && treeVisible && /* @__PURE__ */ jsx6(
1035
+ SubflowTree,
1036
+ {
1037
+ spec,
1038
+ activeStage: overlay?.activeStage,
1039
+ doneStages: overlay?.doneStages,
1040
+ onNodeSelect: handleTreeNodeSelect,
1041
+ unstyled,
1042
+ style: { width: treeWidth, flexShrink: 0, height: "100%" }
1043
+ }
1044
+ ),
1045
+ /* @__PURE__ */ jsxs4("div", { style: { flex: 1, display: "flex", flexDirection: "column", minWidth: 0, height: "100%" }, children: [
1046
+ (subflowNav.isInSubflow || showTree && !treeVisible) && /* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "stretch", flexShrink: 0 }, children: [
1047
+ showTree && !treeVisible && /* @__PURE__ */ jsx6(
1048
+ "button",
1049
+ {
1050
+ onClick: () => setTreeVisible(true),
1051
+ "data-fp": "tree-toggle",
1052
+ style: unstyled ? {} : {
1053
+ background: "transparent",
1054
+ border: "none",
1055
+ cursor: "pointer",
1056
+ padding: "6px 8px",
1057
+ fontSize: 10,
1058
+ flexShrink: 0
1059
+ },
1060
+ children: "\u25B6"
1061
+ }
1062
+ ),
1063
+ /* @__PURE__ */ jsx6("div", { style: { flex: 1 }, children: /* @__PURE__ */ jsx6(
1064
+ SubflowBreadcrumb,
1065
+ {
1066
+ breadcrumbs: subflowNav.breadcrumbs,
1067
+ onNavigate: handleBreadcrumbNavigate
1068
+ }
1069
+ ) })
1070
+ ] }),
1071
+ showTree && treeVisible && /* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "stretch", flexShrink: 0 }, children: [
1072
+ /* @__PURE__ */ jsx6(
1073
+ "button",
1074
+ {
1075
+ onClick: () => setTreeVisible(false),
1076
+ "data-fp": "tree-toggle",
1077
+ style: unstyled ? {} : {
1078
+ background: "transparent",
1079
+ border: "none",
1080
+ cursor: "pointer",
1081
+ padding: "6px 8px",
1082
+ fontSize: 10,
1083
+ flexShrink: 0
1084
+ },
1085
+ children: "\u25C0"
1086
+ }
1087
+ ),
1088
+ /* @__PURE__ */ jsx6("div", { style: { flex: 1 }, children: subflowNav.isInSubflow && /* @__PURE__ */ jsx6(
1089
+ SubflowBreadcrumb,
1090
+ {
1091
+ breadcrumbs: subflowNav.breadcrumbs,
1092
+ onNavigate: handleBreadcrumbNavigate
1093
+ }
1094
+ ) })
1095
+ ] }),
1096
+ /* @__PURE__ */ jsx6("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsx6(
1097
+ ReactFlow2,
1098
+ {
1099
+ nodes,
1100
+ edges,
1101
+ onNodeClick: handleNodeClick,
1102
+ nodeTypes: nodeTypes2,
1103
+ fitView: true,
1104
+ panOnDrag: false,
1105
+ zoomOnScroll: false,
1106
+ zoomOnPinch: false,
1107
+ zoomOnDoubleClick: false,
1108
+ preventScrolling: false,
1109
+ nodesDraggable: false,
1110
+ nodesConnectable: false,
1111
+ elementsSelectable: !!onNodeClick,
1112
+ children: !unstyled && /* @__PURE__ */ jsx6(Background2, { variant: BackgroundVariant2.Dots, gap: 16, size: 1 })
1113
+ }
1114
+ ) })
1115
+ ] })
1116
+ ]
1117
+ }
1118
+ );
1119
+ }
1120
+
690
1121
  // src/components/TimeTravelDebugger/TimeTravelDebugger.tsx
691
- import { useState as useState2 } from "react";
1122
+ import { useState as useState5 } from "react";
692
1123
 
693
1124
  // src/components/MemoryInspector/MemoryInspector.tsx
694
- import { useMemo as useMemo3 } from "react";
695
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1125
+ import { useMemo as useMemo5 } from "react";
1126
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
696
1127
  function MemoryInspector({
697
1128
  data,
698
1129
  snapshots,
@@ -704,7 +1135,7 @@ function MemoryInspector({
704
1135
  className,
705
1136
  style
706
1137
  }) {
707
- const { memory, newKeys } = useMemo3(() => {
1138
+ const { memory, newKeys } = useMemo5(() => {
708
1139
  if (data) {
709
1140
  return { memory: data, newKeys: /* @__PURE__ */ new Set() };
710
1141
  }
@@ -734,12 +1165,12 @@ function MemoryInspector({
734
1165
  const fs = fontSize[size];
735
1166
  const pad = padding[size];
736
1167
  if (unstyled) {
737
- return /* @__PURE__ */ jsxs3("div", { className, style, "data-fp": "memory-inspector", children: [
738
- /* @__PURE__ */ jsx5("div", { "data-fp": "memory-label", children: "Memory State" }),
739
- /* @__PURE__ */ jsx5("pre", { "data-fp": "memory-json", children: JSON.stringify(memory, null, 2) })
1168
+ return /* @__PURE__ */ jsxs5("div", { className, style, "data-fp": "memory-inspector", children: [
1169
+ /* @__PURE__ */ jsx7("div", { "data-fp": "memory-label", children: "Memory State" }),
1170
+ /* @__PURE__ */ jsx7("pre", { "data-fp": "memory-json", children: JSON.stringify(memory, null, 2) })
740
1171
  ] });
741
1172
  }
742
- return /* @__PURE__ */ jsxs3(
1173
+ return /* @__PURE__ */ jsxs5(
743
1174
  "div",
744
1175
  {
745
1176
  className,
@@ -750,7 +1181,7 @@ function MemoryInspector({
750
1181
  },
751
1182
  "data-fp": "memory-inspector",
752
1183
  children: [
753
- /* @__PURE__ */ jsx5(
1184
+ /* @__PURE__ */ jsx7(
754
1185
  "span",
755
1186
  {
756
1187
  style: {
@@ -763,7 +1194,7 @@ function MemoryInspector({
763
1194
  children: "Memory State"
764
1195
  }
765
1196
  ),
766
- /* @__PURE__ */ jsxs3(
1197
+ /* @__PURE__ */ jsxs5(
767
1198
  "div",
768
1199
  {
769
1200
  style: {
@@ -777,8 +1208,8 @@ function MemoryInspector({
777
1208
  lineHeight: 1.8
778
1209
  },
779
1210
  children: [
780
- /* @__PURE__ */ jsx5("span", { style: { color: theme.textMuted }, children: "{" }),
781
- entries.length === 0 && /* @__PURE__ */ jsx5(
1211
+ /* @__PURE__ */ jsx7("span", { style: { color: theme.textMuted }, children: "{" }),
1212
+ entries.length === 0 && /* @__PURE__ */ jsx7(
782
1213
  "div",
783
1214
  {
784
1215
  style: {
@@ -792,7 +1223,7 @@ function MemoryInspector({
792
1223
  entries.map(([key, value], i) => {
793
1224
  const isNew = newKeys.has(key);
794
1225
  const isLast = i === entries.length - 1;
795
- return /* @__PURE__ */ jsxs3(
1226
+ return /* @__PURE__ */ jsxs5(
796
1227
  "div",
797
1228
  {
798
1229
  style: {
@@ -804,14 +1235,14 @@ function MemoryInspector({
804
1235
  paddingRight: 4
805
1236
  },
806
1237
  children: [
807
- /* @__PURE__ */ jsxs3("span", { style: { color: theme.primary }, children: [
1238
+ /* @__PURE__ */ jsxs5("span", { style: { color: theme.primary }, children: [
808
1239
  '"',
809
1240
  key,
810
1241
  '"'
811
1242
  ] }),
812
- /* @__PURE__ */ jsx5("span", { style: { color: theme.textMuted }, children: ": " }),
813
- /* @__PURE__ */ jsx5("span", { style: { color: theme.success }, children: formatValue(value) }),
814
- showTypes && /* @__PURE__ */ jsxs3(
1243
+ /* @__PURE__ */ jsx7("span", { style: { color: theme.textMuted }, children: ": " }),
1244
+ /* @__PURE__ */ jsx7("span", { style: { color: theme.success }, children: formatValue(value) }),
1245
+ showTypes && /* @__PURE__ */ jsxs5(
815
1246
  "span",
816
1247
  {
817
1248
  style: {
@@ -827,13 +1258,13 @@ function MemoryInspector({
827
1258
  ]
828
1259
  }
829
1260
  ),
830
- !isLast && /* @__PURE__ */ jsx5("span", { style: { color: theme.textMuted }, children: "," })
1261
+ !isLast && /* @__PURE__ */ jsx7("span", { style: { color: theme.textMuted }, children: "," })
831
1262
  ]
832
1263
  },
833
1264
  key
834
1265
  );
835
1266
  }),
836
- /* @__PURE__ */ jsx5("span", { style: { color: theme.textMuted }, children: "}" })
1267
+ /* @__PURE__ */ jsx7("span", { style: { color: theme.textMuted }, children: "}" })
837
1268
  ]
838
1269
  }
839
1270
  )
@@ -848,8 +1279,8 @@ function formatValue(value) {
848
1279
  }
849
1280
 
850
1281
  // src/components/NarrativeLog/NarrativeLog.tsx
851
- import { useMemo as useMemo4 } from "react";
852
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1282
+ import { useMemo as useMemo6 } from "react";
1283
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
853
1284
  function NarrativeLog({
854
1285
  snapshots,
855
1286
  selectedIndex,
@@ -859,7 +1290,7 @@ function NarrativeLog({
859
1290
  className,
860
1291
  style
861
1292
  }) {
862
- const entries = useMemo4(() => {
1293
+ const entries = useMemo6(() => {
863
1294
  if (narrative) {
864
1295
  return [{ label: "Output", text: narrative, isCurrent: true }];
865
1296
  }
@@ -873,19 +1304,19 @@ function NarrativeLog({
873
1304
  const fs = fontSize[size];
874
1305
  const pad = padding[size];
875
1306
  if (unstyled) {
876
- return /* @__PURE__ */ jsx6("div", { className, style, "data-fp": "narrative-log", children: entries.map((entry, i) => /* @__PURE__ */ jsxs4("div", { "data-fp": "narrative-entry", "data-current": entry.isCurrent, children: [
877
- /* @__PURE__ */ jsx6("strong", { children: entry.label }),
878
- /* @__PURE__ */ jsx6("p", { children: entry.text })
1307
+ return /* @__PURE__ */ jsx8("div", { className, style, "data-fp": "narrative-log", children: entries.map((entry, i) => /* @__PURE__ */ jsxs6("div", { "data-fp": "narrative-entry", "data-current": entry.isCurrent, children: [
1308
+ /* @__PURE__ */ jsx8("strong", { children: entry.label }),
1309
+ /* @__PURE__ */ jsx8("p", { children: entry.text })
879
1310
  ] }, i)) });
880
1311
  }
881
- return /* @__PURE__ */ jsxs4(
1312
+ return /* @__PURE__ */ jsxs6(
882
1313
  "div",
883
1314
  {
884
1315
  className,
885
1316
  style: { padding: pad, fontFamily: theme.fontSans, ...style },
886
1317
  "data-fp": "narrative-log",
887
1318
  children: [
888
- /* @__PURE__ */ jsx6(
1319
+ /* @__PURE__ */ jsx8(
889
1320
  "span",
890
1321
  {
891
1322
  style: {
@@ -898,7 +1329,7 @@ function NarrativeLog({
898
1329
  children: "Execution Log"
899
1330
  }
900
1331
  ),
901
- /* @__PURE__ */ jsx6("div", { style: { marginTop: 8, display: "flex", flexDirection: "column" }, children: entries.map((entry, i) => /* @__PURE__ */ jsxs4(
1332
+ /* @__PURE__ */ jsx8("div", { style: { marginTop: 8, display: "flex", flexDirection: "column" }, children: entries.map((entry, i) => /* @__PURE__ */ jsxs6(
902
1333
  "div",
903
1334
  {
904
1335
  style: {
@@ -908,7 +1339,7 @@ function NarrativeLog({
908
1339
  borderBottom: i < entries.length - 1 ? `1px solid ${theme.border}` : "none"
909
1340
  },
910
1341
  children: [
911
- /* @__PURE__ */ jsxs4(
1342
+ /* @__PURE__ */ jsxs6(
912
1343
  "div",
913
1344
  {
914
1345
  style: {
@@ -920,7 +1351,7 @@ function NarrativeLog({
920
1351
  paddingTop: 5
921
1352
  },
922
1353
  children: [
923
- /* @__PURE__ */ jsx6(
1354
+ /* @__PURE__ */ jsx8(
924
1355
  "div",
925
1356
  {
926
1357
  style: {
@@ -932,7 +1363,7 @@ function NarrativeLog({
932
1363
  }
933
1364
  }
934
1365
  ),
935
- i < entries.length - 1 && /* @__PURE__ */ jsx6(
1366
+ i < entries.length - 1 && /* @__PURE__ */ jsx8(
936
1367
  "div",
937
1368
  {
938
1369
  style: {
@@ -946,8 +1377,8 @@ function NarrativeLog({
946
1377
  ]
947
1378
  }
948
1379
  ),
949
- /* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0 }, children: [
950
- /* @__PURE__ */ jsx6(
1380
+ /* @__PURE__ */ jsxs6("div", { style: { flex: 1, minWidth: 0 }, children: [
1381
+ /* @__PURE__ */ jsx8(
951
1382
  "span",
952
1383
  {
953
1384
  style: {
@@ -958,7 +1389,7 @@ function NarrativeLog({
958
1389
  children: entry.label
959
1390
  }
960
1391
  ),
961
- /* @__PURE__ */ jsx6(
1392
+ /* @__PURE__ */ jsx8(
962
1393
  "div",
963
1394
  {
964
1395
  style: {
@@ -981,8 +1412,8 @@ function NarrativeLog({
981
1412
  }
982
1413
 
983
1414
  // src/components/GanttTimeline/GanttTimeline.tsx
984
- import { useMemo as useMemo5 } from "react";
985
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1415
+ import { useState as useState4, useMemo as useMemo7, useRef, useEffect } from "react";
1416
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
986
1417
  function GanttTimeline({
987
1418
  snapshots,
988
1419
  selectedIndex = 0,
@@ -990,9 +1421,13 @@ function GanttTimeline({
990
1421
  size = "default",
991
1422
  unstyled = false,
992
1423
  className,
993
- style
1424
+ style,
1425
+ maxVisibleRows = 5
994
1426
  }) {
995
- const totalWallTime = useMemo5(
1427
+ const [expanded, setExpanded] = useState4(false);
1428
+ const activeRowRef = useRef(null);
1429
+ const scrollContainerRef = useRef(null);
1430
+ const totalWallTime = useMemo7(
996
1431
  () => Math.max(...snapshots.map((s) => s.startMs + s.durationMs), 1),
997
1432
  [snapshots]
998
1433
  );
@@ -1000,8 +1435,19 @@ function GanttTimeline({
1000
1435
  const pad = padding[size];
1001
1436
  const labelWidth = size === "compact" ? 50 : size === "detailed" ? 100 : 80;
1002
1437
  const msWidth = size === "compact" ? 28 : 36;
1438
+ const rowHeight = size === "compact" ? 18 : 22;
1439
+ const collapsible = maxVisibleRows > 0 && snapshots.length > maxVisibleRows;
1440
+ const showAll = expanded || !collapsible;
1441
+ useEffect(() => {
1442
+ if (!showAll && activeRowRef.current && scrollContainerRef.current) {
1443
+ activeRowRef.current.scrollIntoView({
1444
+ block: "nearest",
1445
+ behavior: "smooth"
1446
+ });
1447
+ }
1448
+ }, [selectedIndex, showAll]);
1003
1449
  if (unstyled) {
1004
- return /* @__PURE__ */ jsx7("div", { className, style, "data-fp": "gantt-timeline", children: snapshots.map((snap, idx) => /* @__PURE__ */ jsxs5(
1450
+ return /* @__PURE__ */ jsx9("div", { className, style, "data-fp": "gantt-timeline", children: snapshots.map((snap, idx) => /* @__PURE__ */ jsxs7(
1005
1451
  "div",
1006
1452
  {
1007
1453
  "data-fp": "gantt-bar",
@@ -1009,8 +1455,8 @@ function GanttTimeline({
1009
1455
  "data-visible": idx <= selectedIndex,
1010
1456
  onClick: () => onSelect?.(idx),
1011
1457
  children: [
1012
- /* @__PURE__ */ jsx7("span", { "data-fp": "gantt-label", children: snap.stageLabel }),
1013
- /* @__PURE__ */ jsxs5("span", { "data-fp": "gantt-duration", children: [
1458
+ /* @__PURE__ */ jsx9("span", { "data-fp": "gantt-label", children: snap.stageLabel }),
1459
+ /* @__PURE__ */ jsxs7("span", { "data-fp": "gantt-duration", children: [
1014
1460
  snap.durationMs,
1015
1461
  "ms"
1016
1462
  ] })
@@ -1019,43 +1465,79 @@ function GanttTimeline({
1019
1465
  snap.stageName
1020
1466
  )) });
1021
1467
  }
1022
- return /* @__PURE__ */ jsxs5(
1468
+ return /* @__PURE__ */ jsxs7(
1023
1469
  "div",
1024
1470
  {
1025
1471
  className,
1026
1472
  style: { padding: pad, fontFamily: theme.fontSans, ...style },
1027
1473
  "data-fp": "gantt-timeline",
1028
1474
  children: [
1029
- /* @__PURE__ */ jsx7(
1030
- "span",
1475
+ /* @__PURE__ */ jsxs7(
1476
+ "div",
1031
1477
  {
1032
1478
  style: {
1033
- fontSize: fs.label,
1034
- fontWeight: 600,
1035
- color: theme.textMuted,
1036
- textTransform: "uppercase",
1037
- letterSpacing: "0.08em"
1479
+ display: "flex",
1480
+ alignItems: "center",
1481
+ justifyContent: "space-between"
1038
1482
  },
1039
- children: size === "compact" ? "Timeline" : "Execution Timeline"
1483
+ children: [
1484
+ /* @__PURE__ */ jsx9(
1485
+ "span",
1486
+ {
1487
+ style: {
1488
+ fontSize: fs.label,
1489
+ fontWeight: 600,
1490
+ color: theme.textMuted,
1491
+ textTransform: "uppercase",
1492
+ letterSpacing: "0.08em"
1493
+ },
1494
+ children: size === "compact" ? "Timeline" : "Execution Timeline"
1495
+ }
1496
+ ),
1497
+ collapsible && /* @__PURE__ */ jsx9(
1498
+ "button",
1499
+ {
1500
+ onClick: () => setExpanded((e) => !e),
1501
+ style: {
1502
+ background: "none",
1503
+ border: `1px solid ${theme.border}`,
1504
+ borderRadius: 4,
1505
+ color: theme.textSecondary,
1506
+ fontSize: fs.small,
1507
+ padding: "2px 8px",
1508
+ cursor: "pointer",
1509
+ fontFamily: theme.fontSans
1510
+ },
1511
+ children: expanded ? "Collapse" : `${snapshots.length - maxVisibleRows} more...`
1512
+ }
1513
+ )
1514
+ ]
1040
1515
  }
1041
1516
  ),
1042
- /* @__PURE__ */ jsx7(
1517
+ /* @__PURE__ */ jsx9(
1043
1518
  "div",
1044
1519
  {
1520
+ ref: scrollContainerRef,
1045
1521
  style: {
1046
1522
  marginTop: 8,
1047
1523
  display: "flex",
1048
1524
  flexDirection: "column",
1049
- gap: 4
1525
+ gap: 4,
1526
+ ...showAll ? {} : {
1527
+ maxHeight: maxVisibleRows * (rowHeight + 4),
1528
+ overflowY: "auto",
1529
+ scrollbarWidth: "thin"
1530
+ }
1050
1531
  },
1051
1532
  children: snapshots.map((snap, idx) => {
1052
1533
  const leftPct = snap.startMs / totalWallTime * 100;
1053
1534
  const widthPct = Math.max(snap.durationMs / totalWallTime * 100, 1);
1054
1535
  const isSelected = idx === selectedIndex;
1055
1536
  const isVisible = idx <= selectedIndex;
1056
- return /* @__PURE__ */ jsxs5(
1537
+ return /* @__PURE__ */ jsxs7(
1057
1538
  "div",
1058
1539
  {
1540
+ ref: isSelected ? activeRowRef : void 0,
1059
1541
  onClick: () => onSelect?.(idx),
1060
1542
  style: {
1061
1543
  display: "flex",
@@ -1063,10 +1545,12 @@ function GanttTimeline({
1063
1545
  gap: size === "compact" ? 4 : 8,
1064
1546
  cursor: onSelect ? "pointer" : "default",
1065
1547
  opacity: isVisible ? 1 : 0.3,
1066
- transition: "opacity 0.3s ease"
1548
+ transition: "opacity 0.3s ease",
1549
+ height: rowHeight,
1550
+ flexShrink: 0
1067
1551
  },
1068
1552
  children: [
1069
- /* @__PURE__ */ jsx7(
1553
+ /* @__PURE__ */ jsx9(
1070
1554
  "span",
1071
1555
  {
1072
1556
  style: {
@@ -1083,7 +1567,7 @@ function GanttTimeline({
1083
1567
  children: snap.stageLabel
1084
1568
  }
1085
1569
  ),
1086
- /* @__PURE__ */ jsx7(
1570
+ /* @__PURE__ */ jsx9(
1087
1571
  "div",
1088
1572
  {
1089
1573
  style: {
@@ -1093,7 +1577,7 @@ function GanttTimeline({
1093
1577
  background: theme.bgTertiary,
1094
1578
  borderRadius: 3
1095
1579
  },
1096
- children: isVisible && /* @__PURE__ */ jsx7(
1580
+ children: isVisible && /* @__PURE__ */ jsx9(
1097
1581
  "div",
1098
1582
  {
1099
1583
  style: {
@@ -1110,7 +1594,7 @@ function GanttTimeline({
1110
1594
  )
1111
1595
  }
1112
1596
  ),
1113
- /* @__PURE__ */ jsxs5(
1597
+ /* @__PURE__ */ jsxs7(
1114
1598
  "span",
1115
1599
  {
1116
1600
  style: {
@@ -1133,7 +1617,7 @@ function GanttTimeline({
1133
1617
  })
1134
1618
  }
1135
1619
  ),
1136
- /* @__PURE__ */ jsxs5(
1620
+ /* @__PURE__ */ jsxs7(
1137
1621
  "div",
1138
1622
  {
1139
1623
  style: {
@@ -1147,12 +1631,12 @@ function GanttTimeline({
1147
1631
  fontFamily: theme.fontMono
1148
1632
  },
1149
1633
  children: [
1150
- /* @__PURE__ */ jsx7("span", { children: "0ms" }),
1151
- size !== "compact" && /* @__PURE__ */ jsxs5("span", { children: [
1634
+ /* @__PURE__ */ jsx9("span", { children: "0ms" }),
1635
+ size !== "compact" && /* @__PURE__ */ jsxs7("span", { children: [
1152
1636
  (totalWallTime / 2).toFixed(1),
1153
1637
  "ms"
1154
1638
  ] }),
1155
- /* @__PURE__ */ jsxs5("span", { children: [
1639
+ /* @__PURE__ */ jsxs7("span", { children: [
1156
1640
  totalWallTime.toFixed(1),
1157
1641
  "ms"
1158
1642
  ] })
@@ -1165,7 +1649,7 @@ function GanttTimeline({
1165
1649
  }
1166
1650
 
1167
1651
  // src/components/TimeTravelDebugger/TimeTravelDebugger.tsx
1168
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1652
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1169
1653
  function TimeTravelDebugger({
1170
1654
  snapshots,
1171
1655
  nodes,
@@ -1178,11 +1662,11 @@ function TimeTravelDebugger({
1178
1662
  className,
1179
1663
  style
1180
1664
  }) {
1181
- const [selectedIndex, setSelectedIndex] = useState2(0);
1665
+ const [selectedIndex, setSelectedIndex] = useState5(0);
1182
1666
  const fs = fontSize[size];
1183
1667
  const pad = padding[size];
1184
1668
  if (snapshots.length === 0) {
1185
- return /* @__PURE__ */ jsx8(
1669
+ return /* @__PURE__ */ jsx10(
1186
1670
  "div",
1187
1671
  {
1188
1672
  className,
@@ -1198,9 +1682,9 @@ function TimeTravelDebugger({
1198
1682
  }
1199
1683
  const isHorizontal = layout === "horizontal";
1200
1684
  if (unstyled) {
1201
- return /* @__PURE__ */ jsxs6("div", { className, style, "data-fp": "time-travel-debugger", children: [
1202
- /* @__PURE__ */ jsx8("h3", { children: title }),
1203
- /* @__PURE__ */ jsx8(
1685
+ return /* @__PURE__ */ jsxs8("div", { className, style, "data-fp": "time-travel-debugger", children: [
1686
+ /* @__PURE__ */ jsx10("h3", { children: title }),
1687
+ /* @__PURE__ */ jsx10(
1204
1688
  "input",
1205
1689
  {
1206
1690
  type: "range",
@@ -1210,7 +1694,7 @@ function TimeTravelDebugger({
1210
1694
  onChange: (e) => setSelectedIndex(parseInt(e.target.value))
1211
1695
  }
1212
1696
  ),
1213
- /* @__PURE__ */ jsx8(
1697
+ /* @__PURE__ */ jsx10(
1214
1698
  FlowchartView,
1215
1699
  {
1216
1700
  nodes,
@@ -1221,7 +1705,7 @@ function TimeTravelDebugger({
1221
1705
  unstyled: true
1222
1706
  }
1223
1707
  ),
1224
- /* @__PURE__ */ jsx8(
1708
+ /* @__PURE__ */ jsx10(
1225
1709
  MemoryInspector,
1226
1710
  {
1227
1711
  snapshots,
@@ -1229,7 +1713,7 @@ function TimeTravelDebugger({
1229
1713
  unstyled: true
1230
1714
  }
1231
1715
  ),
1232
- /* @__PURE__ */ jsx8(
1716
+ /* @__PURE__ */ jsx10(
1233
1717
  NarrativeLog,
1234
1718
  {
1235
1719
  snapshots,
@@ -1237,7 +1721,7 @@ function TimeTravelDebugger({
1237
1721
  unstyled: true
1238
1722
  }
1239
1723
  ),
1240
- showGantt && /* @__PURE__ */ jsx8(
1724
+ showGantt && /* @__PURE__ */ jsx10(
1241
1725
  GanttTimeline,
1242
1726
  {
1243
1727
  snapshots,
@@ -1248,7 +1732,7 @@ function TimeTravelDebugger({
1248
1732
  )
1249
1733
  ] });
1250
1734
  }
1251
- return /* @__PURE__ */ jsxs6(
1735
+ return /* @__PURE__ */ jsxs8(
1252
1736
  "div",
1253
1737
  {
1254
1738
  className,
@@ -1263,7 +1747,7 @@ function TimeTravelDebugger({
1263
1747
  },
1264
1748
  "data-fp": "time-travel-debugger",
1265
1749
  children: [
1266
- /* @__PURE__ */ jsxs6(
1750
+ /* @__PURE__ */ jsxs8(
1267
1751
  "div",
1268
1752
  {
1269
1753
  style: {
@@ -1273,7 +1757,7 @@ function TimeTravelDebugger({
1273
1757
  flexShrink: 0
1274
1758
  },
1275
1759
  children: [
1276
- /* @__PURE__ */ jsxs6(
1760
+ /* @__PURE__ */ jsxs8(
1277
1761
  "div",
1278
1762
  {
1279
1763
  style: {
@@ -1283,7 +1767,7 @@ function TimeTravelDebugger({
1283
1767
  marginBottom: 8
1284
1768
  },
1285
1769
  children: [
1286
- /* @__PURE__ */ jsx8(
1770
+ /* @__PURE__ */ jsx10(
1287
1771
  "span",
1288
1772
  {
1289
1773
  style: {
@@ -1294,7 +1778,7 @@ function TimeTravelDebugger({
1294
1778
  children: title
1295
1779
  }
1296
1780
  ),
1297
- /* @__PURE__ */ jsx8(
1781
+ /* @__PURE__ */ jsx10(
1298
1782
  "span",
1299
1783
  {
1300
1784
  style: {
@@ -1307,8 +1791,8 @@ function TimeTravelDebugger({
1307
1791
  ]
1308
1792
  }
1309
1793
  ),
1310
- /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
1311
- /* @__PURE__ */ jsx8(
1794
+ /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
1795
+ /* @__PURE__ */ jsx10(
1312
1796
  ScrubButton,
1313
1797
  {
1314
1798
  label: "\\u25C0",
@@ -1316,7 +1800,7 @@ function TimeTravelDebugger({
1316
1800
  onClick: () => setSelectedIndex((i) => Math.max(0, i - 1))
1317
1801
  }
1318
1802
  ),
1319
- /* @__PURE__ */ jsx8(
1803
+ /* @__PURE__ */ jsx10(
1320
1804
  "input",
1321
1805
  {
1322
1806
  type: "range",
@@ -1332,7 +1816,7 @@ function TimeTravelDebugger({
1332
1816
  }
1333
1817
  }
1334
1818
  ),
1335
- /* @__PURE__ */ jsx8(
1819
+ /* @__PURE__ */ jsx10(
1336
1820
  ScrubButton,
1337
1821
  {
1338
1822
  label: "\\u25B6",
@@ -1340,7 +1824,7 @@ function TimeTravelDebugger({
1340
1824
  onClick: () => setSelectedIndex((i) => Math.min(snapshots.length - 1, i + 1))
1341
1825
  }
1342
1826
  ),
1343
- /* @__PURE__ */ jsxs6(
1827
+ /* @__PURE__ */ jsxs8(
1344
1828
  "span",
1345
1829
  {
1346
1830
  style: {
@@ -1360,7 +1844,7 @@ function TimeTravelDebugger({
1360
1844
  ]
1361
1845
  }
1362
1846
  ),
1363
- /* @__PURE__ */ jsxs6(
1847
+ /* @__PURE__ */ jsxs8(
1364
1848
  "div",
1365
1849
  {
1366
1850
  style: {
@@ -1370,7 +1854,7 @@ function TimeTravelDebugger({
1370
1854
  overflow: "hidden"
1371
1855
  },
1372
1856
  children: [
1373
- /* @__PURE__ */ jsx8(
1857
+ /* @__PURE__ */ jsx10(
1374
1858
  "div",
1375
1859
  {
1376
1860
  style: {
@@ -1379,7 +1863,7 @@ function TimeTravelDebugger({
1379
1863
  borderRight: isHorizontal ? `1px solid ${theme.border}` : "none",
1380
1864
  borderBottom: !isHorizontal ? `1px solid ${theme.border}` : "none"
1381
1865
  },
1382
- children: /* @__PURE__ */ jsx8(
1866
+ children: /* @__PURE__ */ jsx10(
1383
1867
  FlowchartView,
1384
1868
  {
1385
1869
  nodes,
@@ -1392,8 +1876,8 @@ function TimeTravelDebugger({
1392
1876
  )
1393
1877
  }
1394
1878
  ),
1395
- /* @__PURE__ */ jsxs6("div", { style: { flex: 1, overflow: "auto" }, children: [
1396
- /* @__PURE__ */ jsx8(
1879
+ /* @__PURE__ */ jsxs8("div", { style: { flex: 1, overflow: "auto" }, children: [
1880
+ /* @__PURE__ */ jsx10(
1397
1881
  MemoryInspector,
1398
1882
  {
1399
1883
  snapshots,
@@ -1401,7 +1885,7 @@ function TimeTravelDebugger({
1401
1885
  size
1402
1886
  }
1403
1887
  ),
1404
- /* @__PURE__ */ jsx8(
1888
+ /* @__PURE__ */ jsx10(
1405
1889
  "div",
1406
1890
  {
1407
1891
  style: {
@@ -1411,7 +1895,7 @@ function TimeTravelDebugger({
1411
1895
  }
1412
1896
  }
1413
1897
  ),
1414
- /* @__PURE__ */ jsx8(
1898
+ /* @__PURE__ */ jsx10(
1415
1899
  NarrativeLog,
1416
1900
  {
1417
1901
  snapshots,
@@ -1423,7 +1907,7 @@ function TimeTravelDebugger({
1423
1907
  ]
1424
1908
  }
1425
1909
  ),
1426
- showGantt && /* @__PURE__ */ jsx8(
1910
+ showGantt && /* @__PURE__ */ jsx10(
1427
1911
  "div",
1428
1912
  {
1429
1913
  style: {
@@ -1431,7 +1915,7 @@ function TimeTravelDebugger({
1431
1915
  background: theme.bgSecondary,
1432
1916
  flexShrink: 0
1433
1917
  },
1434
- children: /* @__PURE__ */ jsx8(
1918
+ children: /* @__PURE__ */ jsx10(
1435
1919
  GanttTimeline,
1436
1920
  {
1437
1921
  snapshots,
@@ -1451,7 +1935,7 @@ function ScrubButton({
1451
1935
  disabled,
1452
1936
  onClick
1453
1937
  }) {
1454
- return /* @__PURE__ */ jsx8(
1938
+ return /* @__PURE__ */ jsx10(
1455
1939
  "button",
1456
1940
  {
1457
1941
  onClick,
@@ -1479,7 +1963,9 @@ export {
1479
1963
  FlowchartView,
1480
1964
  StageNode,
1481
1965
  SubflowBreadcrumb,
1966
+ SubflowTree,
1482
1967
  TimeTravelDebugger,
1968
+ TracedFlowchartView,
1483
1969
  specToReactFlow,
1484
1970
  useSubflowNavigation
1485
1971
  };