footprint-explainable-ui 0.5.0 → 0.7.2
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 +158 -401
- package/dist/flowchart.cjs +764 -531
- package/dist/flowchart.cjs.map +1 -1
- package/dist/flowchart.d.cts +68 -15
- package/dist/flowchart.d.ts +68 -15
- package/dist/flowchart.js +734 -502
- package/dist/flowchart.js.map +1 -1
- package/dist/index.cjs +1248 -485
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +171 -33
- package/dist/index.d.ts +171 -33
- package/dist/index.js +1225 -469
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/flowchart.cjs
CHANGED
|
@@ -26,24 +26,26 @@ __export(flowchart_exports, {
|
|
|
26
26
|
SubflowTree: () => SubflowTree,
|
|
27
27
|
TimeTravelDebugger: () => TimeTravelDebugger,
|
|
28
28
|
TracedFlowchartView: () => TracedFlowchartView,
|
|
29
|
+
applyOverlay: () => applyOverlay,
|
|
30
|
+
specToLayout: () => specToLayout,
|
|
29
31
|
specToReactFlow: () => specToReactFlow,
|
|
30
32
|
useSubflowNavigation: () => useSubflowNavigation
|
|
31
33
|
});
|
|
32
34
|
module.exports = __toCommonJS(flowchart_exports);
|
|
33
35
|
|
|
34
36
|
// src/components/FlowchartView/FlowchartView.tsx
|
|
35
|
-
var
|
|
36
|
-
var
|
|
37
|
+
var import_react5 = require("react");
|
|
38
|
+
var import_react6 = require("@xyflow/react");
|
|
37
39
|
|
|
38
40
|
// src/components/StageNode/StageNode.tsx
|
|
39
|
-
var
|
|
40
|
-
var
|
|
41
|
+
var import_react3 = require("react");
|
|
42
|
+
var import_react4 = require("@xyflow/react");
|
|
41
43
|
|
|
42
44
|
// src/theme/ThemeProvider.tsx
|
|
43
45
|
var import_react = require("react");
|
|
44
46
|
|
|
45
47
|
// src/theme/tokens.ts
|
|
46
|
-
var
|
|
48
|
+
var rawDefaults = {
|
|
47
49
|
colors: {
|
|
48
50
|
primary: "#6366f1",
|
|
49
51
|
success: "#22c55e",
|
|
@@ -63,6 +65,26 @@ var defaultTokens = {
|
|
|
63
65
|
mono: "'JetBrains Mono', 'Fira Code', monospace"
|
|
64
66
|
}
|
|
65
67
|
};
|
|
68
|
+
var defaultTokens = {
|
|
69
|
+
colors: {
|
|
70
|
+
primary: `var(--fp-color-primary, ${rawDefaults.colors.primary})`,
|
|
71
|
+
success: `var(--fp-color-success, ${rawDefaults.colors.success})`,
|
|
72
|
+
error: `var(--fp-color-error, ${rawDefaults.colors.error})`,
|
|
73
|
+
warning: `var(--fp-color-warning, ${rawDefaults.colors.warning})`,
|
|
74
|
+
bgPrimary: `var(--fp-bg-primary, ${rawDefaults.colors.bgPrimary})`,
|
|
75
|
+
bgSecondary: `var(--fp-bg-secondary, ${rawDefaults.colors.bgSecondary})`,
|
|
76
|
+
bgTertiary: `var(--fp-bg-tertiary, ${rawDefaults.colors.bgTertiary})`,
|
|
77
|
+
textPrimary: `var(--fp-text-primary, ${rawDefaults.colors.textPrimary})`,
|
|
78
|
+
textSecondary: `var(--fp-text-secondary, ${rawDefaults.colors.textSecondary})`,
|
|
79
|
+
textMuted: `var(--fp-text-muted, ${rawDefaults.colors.textMuted})`,
|
|
80
|
+
border: `var(--fp-border, ${rawDefaults.colors.border})`
|
|
81
|
+
},
|
|
82
|
+
radius: `var(--fp-radius, ${rawDefaults.radius})`,
|
|
83
|
+
fontFamily: {
|
|
84
|
+
sans: `var(--fp-font-sans, ${rawDefaults.fontFamily.sans})`,
|
|
85
|
+
mono: `var(--fp-font-mono, ${rawDefaults.fontFamily.mono})`
|
|
86
|
+
}
|
|
87
|
+
};
|
|
66
88
|
|
|
67
89
|
// src/theme/ThemeProvider.tsx
|
|
68
90
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -99,19 +121,181 @@ var padding = {
|
|
|
99
121
|
detailed: 16
|
|
100
122
|
};
|
|
101
123
|
|
|
124
|
+
// src/theme/useDarkModeTokens.ts
|
|
125
|
+
var import_react2 = require("react");
|
|
126
|
+
|
|
102
127
|
// src/components/StageNode/StageNode.tsx
|
|
103
128
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
104
|
-
var
|
|
129
|
+
var KEYFRAMES_ID = "fp-stage-node-keyframes";
|
|
130
|
+
var KEYFRAMES_CSS = `
|
|
131
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
132
|
+
@keyframes fp-pulse {
|
|
133
|
+
0%, 100% { opacity: 0.4; transform: scale(1); }
|
|
134
|
+
50% { opacity: 0.15; transform: scale(1.06); }
|
|
135
|
+
}
|
|
136
|
+
@keyframes fp-blink {
|
|
137
|
+
0%, 100% { opacity: 1; }
|
|
138
|
+
50% { opacity: 0.3; }
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
@media (prefers-reduced-motion: reduce) {
|
|
142
|
+
@keyframes fp-pulse { 0%, 100% { opacity: 0.3; } }
|
|
143
|
+
@keyframes fp-blink { 0%, 100% { opacity: 1; } }
|
|
144
|
+
}
|
|
145
|
+
`;
|
|
146
|
+
var ICON_SIZE = 16;
|
|
147
|
+
function StageIcon({ type, color }) {
|
|
148
|
+
const s = ICON_SIZE;
|
|
149
|
+
const props = { width: s, height: s, viewBox: `0 0 ${s} ${s}`, fill: "none", style: { flexShrink: 0 } };
|
|
150
|
+
switch (type) {
|
|
151
|
+
// LLM / AI call — brain/sparkle
|
|
152
|
+
case "llm":
|
|
153
|
+
case "ai":
|
|
154
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
155
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "8", cy: "8", r: "6", stroke: color, strokeWidth: "1.5" }),
|
|
156
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5.5 8C5.5 6.5 6.5 5 8 5S10.5 6.5 10.5 8", stroke: color, strokeWidth: "1.2", strokeLinecap: "round" }),
|
|
157
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "8", cy: "9.5", r: "1", fill: color }),
|
|
158
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "8", y1: "2", x2: "8", y2: "3.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
|
|
159
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12.5", y1: "4", x2: "11.2", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
|
|
160
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "3.5", y1: "4", x2: "4.8", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
|
|
161
|
+
] });
|
|
162
|
+
// Tool / function call — gear
|
|
163
|
+
case "tool":
|
|
164
|
+
case "function":
|
|
165
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
166
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "8", cy: "8", r: "3", stroke: color, strokeWidth: "1.5" }),
|
|
167
|
+
[0, 45, 90, 135, 180, 225, 270, 315].map((angle) => {
|
|
168
|
+
const rad = angle * Math.PI / 180;
|
|
169
|
+
const x1 = 8 + Math.cos(rad) * 4.5;
|
|
170
|
+
const y1 = 8 + Math.sin(rad) * 4.5;
|
|
171
|
+
const x2 = 8 + Math.cos(rad) * 6;
|
|
172
|
+
const y2 = 8 + Math.sin(rad) * 6;
|
|
173
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1, y1, x2, y2, stroke: color, strokeWidth: "1.5", strokeLinecap: "round" }, angle);
|
|
174
|
+
})
|
|
175
|
+
] });
|
|
176
|
+
// RAG / retrieval — magnifying glass + doc
|
|
177
|
+
case "rag":
|
|
178
|
+
case "search":
|
|
179
|
+
case "retrieval":
|
|
180
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
181
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "7", cy: "7", r: "4", stroke: color, strokeWidth: "1.5" }),
|
|
182
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "10", y1: "10", x2: "13.5", y2: "13.5", stroke: color, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
183
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "5.5", y1: "6", x2: "8.5", y2: "6", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
|
|
184
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "5.5", y1: "8", x2: "7.5", y2: "8", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
|
|
185
|
+
] });
|
|
186
|
+
// Parse / process — diamond with arrows
|
|
187
|
+
case "parse":
|
|
188
|
+
case "process":
|
|
189
|
+
case "transform":
|
|
190
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: color, strokeWidth: "1.5", transform: "rotate(45 8 8)" }) });
|
|
191
|
+
// Start / seed — play triangle
|
|
192
|
+
case "start":
|
|
193
|
+
case "seed":
|
|
194
|
+
case "init":
|
|
195
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 3.5L12.5 8L5 12.5V3.5Z", fill: color, opacity: "0.8" }) });
|
|
196
|
+
// End / finalize — stop square
|
|
197
|
+
case "end":
|
|
198
|
+
case "finalize":
|
|
199
|
+
case "output":
|
|
200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", fill: color, opacity: "0.8" }) });
|
|
201
|
+
// Agent — person silhouette
|
|
202
|
+
case "agent":
|
|
203
|
+
case "orchestrator":
|
|
204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "8", cy: "5", r: "2.5", stroke: color, strokeWidth: "1.5" }),
|
|
206
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M3.5 14C3.5 11 5.5 9 8 9S12.5 11 12.5 14", stroke: color, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
207
|
+
] });
|
|
208
|
+
// Swarm — multi-agent
|
|
209
|
+
case "swarm":
|
|
210
|
+
case "multi-agent":
|
|
211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
212
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5", cy: "5", r: "2", stroke: color, strokeWidth: "1.2" }),
|
|
213
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "11", cy: "5", r: "2", stroke: color, strokeWidth: "1.2" }),
|
|
214
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "8", cy: "11", r: "2", stroke: color, strokeWidth: "1.2" }),
|
|
215
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "5", y1: "7", x2: "8", y2: "9", stroke: color, strokeWidth: "1", opacity: "0.5" }),
|
|
216
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "11", y1: "7", x2: "8", y2: "9", stroke: color, strokeWidth: "1", opacity: "0.5" })
|
|
217
|
+
] });
|
|
218
|
+
// Guard / guardrail — shield
|
|
219
|
+
case "guard":
|
|
220
|
+
case "guardrail":
|
|
221
|
+
case "validate":
|
|
222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
223
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 2L3 5V9C3 11.5 5 13.5 8 14.5C11 13.5 13 11.5 13 9V5L8 2Z", stroke: color, strokeWidth: "1.5", strokeLinejoin: "round" }),
|
|
224
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 8L7.5 9.5L10 6.5", stroke: color, strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
225
|
+
] });
|
|
226
|
+
// Stream — wave
|
|
227
|
+
case "stream":
|
|
228
|
+
case "streaming":
|
|
229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
230
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M2 8C4 5 6 11 8 8S12 5 14 8", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", fill: "none" }),
|
|
231
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M2 11C4 8 6 14 8 11S12 8 14 11", stroke: color, strokeWidth: "1", strokeLinecap: "round", fill: "none", opacity: "0.5" })
|
|
232
|
+
] });
|
|
233
|
+
// Memory / state — database cylinder
|
|
234
|
+
case "memory":
|
|
235
|
+
case "state":
|
|
236
|
+
case "db":
|
|
237
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
238
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ellipse", { cx: "8", cy: "4.5", rx: "5", ry: "2", stroke: color, strokeWidth: "1.3" }),
|
|
239
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "3", y1: "4.5", x2: "3", y2: "11.5", stroke: color, strokeWidth: "1.3" }),
|
|
240
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "13", y1: "4.5", x2: "13", y2: "11.5", stroke: color, strokeWidth: "1.3" }),
|
|
241
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ellipse", { cx: "8", cy: "11.5", rx: "5", ry: "2", stroke: color, strokeWidth: "1.3" })
|
|
242
|
+
] });
|
|
243
|
+
// Loop — circular arrow
|
|
244
|
+
case "loop":
|
|
245
|
+
case "retry":
|
|
246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
247
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 8A4 4 0 1 1 8 4", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", fill: "none" }),
|
|
248
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 1.5L10.5 4L8 6.5", stroke: color, strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" })
|
|
249
|
+
] });
|
|
250
|
+
// Lazy / service — cloud (deferred resolution, loaded on demand)
|
|
251
|
+
case "lazy":
|
|
252
|
+
case "service":
|
|
253
|
+
case "cloud":
|
|
254
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
255
|
+
"path",
|
|
256
|
+
{
|
|
257
|
+
d: "M4.5 12C2.8 12 1.5 10.7 1.5 9C1.5 7.5 2.5 6.3 3.8 6C4 4 5.8 2.5 8 2.5C9.8 2.5 11.3 3.5 11.9 5C13.9 5.2 15.5 6.8 15.5 8.8C15.5 10.8 13.9 12.5 11.8 12.5H4.5",
|
|
258
|
+
stroke: color,
|
|
259
|
+
strokeWidth: "1.3",
|
|
260
|
+
strokeLinecap: "round",
|
|
261
|
+
fill: "none"
|
|
262
|
+
}
|
|
263
|
+
) });
|
|
264
|
+
// Decision — diamond (already handled by isDecider shape)
|
|
265
|
+
case "decision":
|
|
266
|
+
case "router":
|
|
267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
|
|
268
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 2L14 8L8 14L2 8Z", stroke: color, strokeWidth: "1.5", fill: "none" }),
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "8", cy: "8", r: "1.5", fill: color })
|
|
270
|
+
] });
|
|
271
|
+
default:
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
var StageNode = (0, import_react3.memo)(function StageNode2({
|
|
105
276
|
data
|
|
106
277
|
}) {
|
|
107
|
-
const { label, active, done, error, linked, stepNumbers, dimmed, isSubflow, description } = data;
|
|
278
|
+
const { label, active, done, error, linked, icon, stepNumbers, dimmed, isSubflow, isLazy, isDecider, isFork, description } = data;
|
|
279
|
+
const effectiveIcon = icon || (isLazy ? "lazy" : void 0);
|
|
280
|
+
const isLazyUnresolved = isLazy && !done && !active;
|
|
281
|
+
const injectedRef = (0, import_react3.useRef)(false);
|
|
282
|
+
(0, import_react3.useEffect)(() => {
|
|
283
|
+
if (injectedRef.current) return;
|
|
284
|
+
if (typeof document !== "undefined" && !document.getElementById(KEYFRAMES_ID)) {
|
|
285
|
+
const styleEl = document.createElement("style");
|
|
286
|
+
styleEl.id = KEYFRAMES_ID;
|
|
287
|
+
styleEl.textContent = KEYFRAMES_CSS;
|
|
288
|
+
document.head.appendChild(styleEl);
|
|
289
|
+
}
|
|
290
|
+
injectedRef.current = true;
|
|
291
|
+
}, []);
|
|
108
292
|
const isOnPath = active || done;
|
|
109
293
|
const bg = active ? theme.primary : done ? theme.success : error ? theme.error : theme.bgSecondary;
|
|
110
294
|
const borderColor = active ? theme.primary : done ? theme.success : error ? theme.error : theme.border;
|
|
111
295
|
const shadow = active ? `0 0 16px color-mix(in srgb, ${theme.primary} 40%, transparent)` : done ? `0 0 8px color-mix(in srgb, ${theme.success} 20%, transparent)` : error ? `0 0 12px color-mix(in srgb, ${theme.error} 30%, transparent)` : `0 2px 8px rgba(0,0,0,0.15)`;
|
|
112
296
|
const textColor = active || done || error ? "#fff" : theme.textPrimary;
|
|
113
297
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
114
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react4.Handle, { type: "target", position: import_react4.Position.Top, style: { opacity: 0 } }),
|
|
115
299
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
116
300
|
"div",
|
|
117
301
|
{
|
|
@@ -166,7 +350,8 @@ var StageNode = (0, import_react2.memo)(function StageNode2({
|
|
|
166
350
|
style: {
|
|
167
351
|
position: "absolute",
|
|
168
352
|
inset: -6,
|
|
169
|
-
borderRadius: `calc(${theme.radius} + 4px)`,
|
|
353
|
+
borderRadius: isDecider ? 0 : `calc(${theme.radius} + 4px)`,
|
|
354
|
+
transform: isDecider ? "rotate(45deg)" : void 0,
|
|
170
355
|
border: `2px solid ${theme.primary}`,
|
|
171
356
|
opacity: 0.4,
|
|
172
357
|
animation: "fp-pulse 2s ease-in-out infinite"
|
|
@@ -179,127 +364,195 @@ var StageNode = (0, import_react2.memo)(function StageNode2({
|
|
|
179
364
|
style: {
|
|
180
365
|
position: "absolute",
|
|
181
366
|
inset: -6,
|
|
182
|
-
borderRadius: `calc(${theme.radius} + 4px)`,
|
|
367
|
+
borderRadius: isDecider ? 0 : `calc(${theme.radius} + 4px)`,
|
|
368
|
+
transform: isDecider ? "rotate(45deg)" : void 0,
|
|
183
369
|
border: `2px solid ${theme.primary}`,
|
|
184
370
|
opacity: 0.3,
|
|
185
371
|
animation: "fp-pulse 1.5s ease-out infinite"
|
|
186
372
|
}
|
|
187
373
|
}
|
|
188
374
|
),
|
|
189
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
375
|
+
isDecider ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
190
376
|
"div",
|
|
191
377
|
{
|
|
192
378
|
style: {
|
|
193
379
|
background: bg,
|
|
194
|
-
border: `2px solid ${borderColor}`,
|
|
195
|
-
borderRadius:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
flexDirection: "column",
|
|
199
|
-
alignItems: "center",
|
|
200
|
-
gap: description ? 2 : 0,
|
|
380
|
+
border: `2px ${isLazyUnresolved ? "dashed" : "solid"} ${borderColor}`,
|
|
381
|
+
borderRadius: 4,
|
|
382
|
+
transform: "rotate(45deg)",
|
|
383
|
+
padding: 20,
|
|
201
384
|
boxShadow: shadow,
|
|
202
385
|
transition: "all 0.3s ease",
|
|
203
|
-
|
|
204
|
-
|
|
386
|
+
display: "flex",
|
|
387
|
+
alignItems: "center",
|
|
205
388
|
justifyContent: "center"
|
|
206
389
|
},
|
|
207
|
-
children:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
"
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
390
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
391
|
+
"div",
|
|
392
|
+
{
|
|
393
|
+
style: {
|
|
394
|
+
transform: "rotate(-45deg)",
|
|
395
|
+
display: "flex",
|
|
396
|
+
flexDirection: "column",
|
|
397
|
+
alignItems: "center",
|
|
398
|
+
gap: 2,
|
|
399
|
+
fontFamily: theme.fontSans
|
|
400
|
+
},
|
|
401
|
+
children: [
|
|
402
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [
|
|
403
|
+
icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StageIcon, { type: icon, color: textColor }),
|
|
404
|
+
!icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: 10, color: textColor }, children: "\u25C7" }),
|
|
405
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
406
|
+
"span",
|
|
407
|
+
{
|
|
408
|
+
style: {
|
|
409
|
+
fontSize: 12,
|
|
410
|
+
fontWeight: 600,
|
|
411
|
+
color: textColor,
|
|
412
|
+
whiteSpace: "nowrap"
|
|
413
|
+
},
|
|
414
|
+
children: label
|
|
415
|
+
}
|
|
416
|
+
)
|
|
417
|
+
] }),
|
|
418
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
419
|
+
"span",
|
|
420
|
+
{
|
|
421
|
+
style: {
|
|
422
|
+
fontSize: 9,
|
|
423
|
+
fontWeight: 400,
|
|
424
|
+
color: textColor,
|
|
425
|
+
opacity: 0.7,
|
|
426
|
+
whiteSpace: "nowrap",
|
|
427
|
+
overflow: "hidden",
|
|
428
|
+
textOverflow: "ellipsis",
|
|
429
|
+
maxWidth: 130
|
|
430
|
+
},
|
|
431
|
+
children: description
|
|
220
432
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
433
|
+
)
|
|
434
|
+
]
|
|
435
|
+
}
|
|
436
|
+
)
|
|
437
|
+
}
|
|
438
|
+
) : (
|
|
439
|
+
/* Standard rectangular node */
|
|
440
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
441
|
+
"div",
|
|
442
|
+
{
|
|
443
|
+
style: {
|
|
444
|
+
background: bg,
|
|
445
|
+
border: `2px ${isLazyUnresolved ? "dashed" : "solid"} ${borderColor}`,
|
|
446
|
+
borderRadius: theme.radius,
|
|
447
|
+
padding: description ? "8px 16px" : "10px 20px",
|
|
448
|
+
display: "flex",
|
|
449
|
+
flexDirection: "column",
|
|
450
|
+
alignItems: "center",
|
|
451
|
+
gap: description ? 2 : 0,
|
|
452
|
+
boxShadow: shadow,
|
|
453
|
+
transition: "all 0.3s ease",
|
|
454
|
+
fontFamily: theme.fontSans,
|
|
455
|
+
minWidth: 100,
|
|
456
|
+
justifyContent: "center"
|
|
457
|
+
},
|
|
458
|
+
children: [
|
|
459
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
460
|
+
effectiveIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StageIcon, { type: effectiveIcon, color: textColor }),
|
|
461
|
+
done && !effectiveIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: 10, color: textColor }, children: "\u2713" }),
|
|
462
|
+
active && !effectiveIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
463
|
+
"span",
|
|
464
|
+
{
|
|
465
|
+
style: {
|
|
466
|
+
width: 8,
|
|
467
|
+
height: 8,
|
|
468
|
+
borderRadius: "50%",
|
|
469
|
+
background: "#fff",
|
|
470
|
+
animation: "fp-blink 1s ease-in-out infinite",
|
|
471
|
+
flexShrink: 0
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
),
|
|
475
|
+
error && !effectiveIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: 10, color: textColor }, children: "\u2717" }),
|
|
476
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
477
|
+
"span",
|
|
478
|
+
{
|
|
479
|
+
style: {
|
|
480
|
+
fontSize: 13,
|
|
481
|
+
fontWeight: 500,
|
|
482
|
+
color: textColor,
|
|
483
|
+
whiteSpace: "nowrap"
|
|
484
|
+
},
|
|
485
|
+
children: label
|
|
486
|
+
}
|
|
487
|
+
),
|
|
488
|
+
isSubflow && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
489
|
+
"span",
|
|
490
|
+
{
|
|
491
|
+
style: {
|
|
492
|
+
display: "inline-flex",
|
|
493
|
+
alignItems: "center",
|
|
494
|
+
justifyContent: "center",
|
|
495
|
+
width: 16,
|
|
496
|
+
height: 16,
|
|
497
|
+
borderRadius: 3,
|
|
498
|
+
border: `1.5px solid ${textColor}`,
|
|
499
|
+
position: "relative",
|
|
500
|
+
opacity: 0.7,
|
|
501
|
+
flexShrink: 0
|
|
502
|
+
},
|
|
503
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
504
|
+
"span",
|
|
505
|
+
{
|
|
506
|
+
style: {
|
|
507
|
+
width: 8,
|
|
508
|
+
height: 8,
|
|
509
|
+
borderRadius: 2,
|
|
510
|
+
border: `1px solid ${textColor}`
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
)
|
|
514
|
+
}
|
|
515
|
+
)
|
|
516
|
+
] }),
|
|
517
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
225
518
|
"span",
|
|
226
519
|
{
|
|
227
520
|
style: {
|
|
228
|
-
fontSize:
|
|
229
|
-
fontWeight:
|
|
521
|
+
fontSize: 10,
|
|
522
|
+
fontWeight: 400,
|
|
230
523
|
color: textColor,
|
|
231
|
-
whiteSpace: "nowrap"
|
|
232
|
-
},
|
|
233
|
-
children: label
|
|
234
|
-
}
|
|
235
|
-
),
|
|
236
|
-
isSubflow && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
237
|
-
"span",
|
|
238
|
-
{
|
|
239
|
-
style: {
|
|
240
|
-
display: "inline-flex",
|
|
241
|
-
alignItems: "center",
|
|
242
|
-
justifyContent: "center",
|
|
243
|
-
width: 16,
|
|
244
|
-
height: 16,
|
|
245
|
-
borderRadius: 3,
|
|
246
|
-
border: `1.5px solid ${textColor}`,
|
|
247
|
-
position: "relative",
|
|
248
524
|
opacity: 0.7,
|
|
249
|
-
|
|
525
|
+
whiteSpace: "nowrap",
|
|
526
|
+
overflow: "hidden",
|
|
527
|
+
textOverflow: "ellipsis",
|
|
528
|
+
maxWidth: 160
|
|
250
529
|
},
|
|
251
|
-
children:
|
|
252
|
-
"span",
|
|
253
|
-
{
|
|
254
|
-
style: {
|
|
255
|
-
width: 8,
|
|
256
|
-
height: 8,
|
|
257
|
-
borderRadius: 2,
|
|
258
|
-
border: `1px solid ${textColor}`
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
)
|
|
530
|
+
children: description
|
|
262
531
|
}
|
|
263
532
|
)
|
|
264
|
-
]
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
{
|
|
268
|
-
style: {
|
|
269
|
-
fontSize: 10,
|
|
270
|
-
fontWeight: 400,
|
|
271
|
-
color: textColor,
|
|
272
|
-
opacity: 0.7,
|
|
273
|
-
whiteSpace: "nowrap",
|
|
274
|
-
overflow: "hidden",
|
|
275
|
-
textOverflow: "ellipsis",
|
|
276
|
-
maxWidth: 160
|
|
277
|
-
},
|
|
278
|
-
children: description
|
|
279
|
-
}
|
|
280
|
-
)
|
|
281
|
-
]
|
|
282
|
-
}
|
|
533
|
+
]
|
|
534
|
+
}
|
|
535
|
+
)
|
|
283
536
|
)
|
|
284
537
|
]
|
|
285
538
|
}
|
|
286
539
|
),
|
|
287
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
540
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react4.Handle, { type: "source", position: import_react4.Position.Bottom, style: { opacity: 0 } }),
|
|
288
541
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
289
|
-
|
|
542
|
+
import_react4.Handle,
|
|
290
543
|
{
|
|
291
544
|
id: "loop-source",
|
|
292
545
|
type: "source",
|
|
293
|
-
position:
|
|
546
|
+
position: import_react4.Position.Right,
|
|
294
547
|
style: { background: "transparent", border: "none", width: 6, height: 6 }
|
|
295
548
|
}
|
|
296
549
|
),
|
|
297
550
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
298
|
-
|
|
551
|
+
import_react4.Handle,
|
|
299
552
|
{
|
|
300
553
|
id: "loop-target",
|
|
301
554
|
type: "target",
|
|
302
|
-
position:
|
|
555
|
+
position: import_react4.Position.Right,
|
|
303
556
|
style: { background: "transparent", border: "none", width: 6, height: 6 }
|
|
304
557
|
}
|
|
305
558
|
)
|
|
@@ -319,7 +572,7 @@ function FlowchartView({
|
|
|
319
572
|
className,
|
|
320
573
|
style
|
|
321
574
|
}) {
|
|
322
|
-
const enhancedNodes = (0,
|
|
575
|
+
const enhancedNodes = (0, import_react5.useMemo)(() => {
|
|
323
576
|
if (!snapshots || snapshots.length === 0) {
|
|
324
577
|
return rawNodes.map((n) => ({
|
|
325
578
|
...n,
|
|
@@ -349,7 +602,7 @@ function FlowchartView({
|
|
|
349
602
|
}
|
|
350
603
|
}));
|
|
351
604
|
}, [rawNodes, snapshots, selectedIndex]);
|
|
352
|
-
const enhancedEdges = (0,
|
|
605
|
+
const enhancedEdges = (0, import_react5.useMemo)(() => {
|
|
353
606
|
if (!snapshots || snapshots.length === 0) {
|
|
354
607
|
return rawEdges.map((e) => ({
|
|
355
608
|
...e,
|
|
@@ -374,9 +627,9 @@ function FlowchartView({
|
|
|
374
627
|
};
|
|
375
628
|
});
|
|
376
629
|
}, [rawEdges, snapshots, selectedIndex]);
|
|
377
|
-
const [nodes, , onNodesChange] = (0,
|
|
378
|
-
const [edges, , onEdgesChange] = (0,
|
|
379
|
-
const handleNodeClick = (0,
|
|
630
|
+
const [nodes, , onNodesChange] = (0, import_react6.useNodesState)(enhancedNodes);
|
|
631
|
+
const [edges, , onEdgesChange] = (0, import_react6.useEdgesState)(enhancedEdges);
|
|
632
|
+
const handleNodeClick = (0, import_react5.useCallback)(
|
|
380
633
|
(_, node) => {
|
|
381
634
|
if (!onNodeClick || !snapshots) return;
|
|
382
635
|
const idx = snapshots.findIndex((s) => s.stageName === node.id);
|
|
@@ -395,7 +648,7 @@ function FlowchartView({
|
|
|
395
648
|
},
|
|
396
649
|
"data-fp": "flowchart-view",
|
|
397
650
|
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
398
|
-
|
|
651
|
+
import_react6.ReactFlow,
|
|
399
652
|
{
|
|
400
653
|
nodes,
|
|
401
654
|
edges,
|
|
@@ -412,7 +665,7 @@ function FlowchartView({
|
|
|
412
665
|
nodesDraggable: false,
|
|
413
666
|
nodesConnectable: false,
|
|
414
667
|
elementsSelectable: !!onNodeClick,
|
|
415
|
-
children: !unstyled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
668
|
+
children: !unstyled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react6.Background, { variant: import_react6.BackgroundVariant.Dots, gap: 16, size: 1 })
|
|
416
669
|
}
|
|
417
670
|
)
|
|
418
671
|
}
|
|
@@ -420,19 +673,19 @@ function FlowchartView({
|
|
|
420
673
|
}
|
|
421
674
|
|
|
422
675
|
// src/components/FlowchartView/TracedFlowchartView.tsx
|
|
423
|
-
var
|
|
424
|
-
var
|
|
676
|
+
var import_react7 = require("react");
|
|
677
|
+
var import_react8 = require("@xyflow/react");
|
|
425
678
|
|
|
426
679
|
// src/components/FlowchartView/specToReactFlow.ts
|
|
427
680
|
var DEFAULT_COLORS = {
|
|
428
|
-
edgeDefault:
|
|
429
|
-
edgeExecuted:
|
|
430
|
-
edgeActive:
|
|
431
|
-
edgeLoop:
|
|
432
|
-
labelDefault:
|
|
433
|
-
labelExecuted:
|
|
434
|
-
labelLoop:
|
|
435
|
-
pathGlow: `${
|
|
681
|
+
edgeDefault: rawDefaults.colors.textMuted,
|
|
682
|
+
edgeExecuted: rawDefaults.colors.success,
|
|
683
|
+
edgeActive: rawDefaults.colors.primary,
|
|
684
|
+
edgeLoop: rawDefaults.colors.warning,
|
|
685
|
+
labelDefault: rawDefaults.colors.textSecondary,
|
|
686
|
+
labelExecuted: rawDefaults.colors.success,
|
|
687
|
+
labelLoop: rawDefaults.colors.warning,
|
|
688
|
+
pathGlow: `${rawDefaults.colors.success}4D`
|
|
436
689
|
// ~30% opacity hex
|
|
437
690
|
};
|
|
438
691
|
var Y_STEP = 100;
|
|
@@ -440,122 +693,33 @@ var X_SPREAD = 200;
|
|
|
440
693
|
function nid(n) {
|
|
441
694
|
return n.name || n.id || `spec-${Math.random()}`;
|
|
442
695
|
}
|
|
443
|
-
function
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
const c = state.colors;
|
|
447
|
-
const executed = o && o.executedStages.has(source) && o.executedStages.has(target);
|
|
448
|
-
const isLeadingEdge = o && source === o.activeStage && !o.doneStages.has(target);
|
|
449
|
-
if (isLoop) {
|
|
450
|
-
let loopExecuted = false;
|
|
451
|
-
if (o?.executionOrder) {
|
|
452
|
-
const lastSourceIdx = o.executionOrder.lastIndexOf(source);
|
|
453
|
-
if (lastSourceIdx >= 0) {
|
|
454
|
-
loopExecuted = o.executionOrder.slice(lastSourceIdx + 1).includes(target);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
state.edges.push({
|
|
458
|
-
id: `se${state.edgeCounter}`,
|
|
459
|
-
source,
|
|
460
|
-
target,
|
|
461
|
-
sourceHandle: "loop-source",
|
|
462
|
-
targetHandle: "loop-target",
|
|
463
|
-
label: label ?? "loop",
|
|
464
|
-
type: "smoothstep",
|
|
465
|
-
pathOptions: { offset: 40, borderRadius: 16 },
|
|
466
|
-
style: {
|
|
467
|
-
stroke: c.edgeLoop,
|
|
468
|
-
strokeWidth: loopExecuted ? 3 : 2,
|
|
469
|
-
strokeDasharray: "6 3",
|
|
470
|
-
opacity: o && !loopExecuted ? 0.35 : 1
|
|
471
|
-
},
|
|
472
|
-
labelStyle: { fontSize: 10, fontWeight: 700, fill: c.labelLoop },
|
|
473
|
-
animated: loopExecuted,
|
|
474
|
-
zIndex: 2
|
|
475
|
-
});
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
if (executed) {
|
|
479
|
-
state.edges.push({
|
|
480
|
-
id: `se${state.edgeCounter}-glow`,
|
|
481
|
-
source,
|
|
482
|
-
target,
|
|
483
|
-
style: {
|
|
484
|
-
stroke: c.pathGlow,
|
|
485
|
-
strokeWidth: 8,
|
|
486
|
-
opacity: 0.4
|
|
487
|
-
},
|
|
488
|
-
zIndex: 0,
|
|
489
|
-
selectable: false,
|
|
490
|
-
focusable: false
|
|
491
|
-
});
|
|
492
|
-
state.edges.push({
|
|
493
|
-
id: `se${state.edgeCounter}`,
|
|
494
|
-
source,
|
|
495
|
-
target,
|
|
496
|
-
label,
|
|
497
|
-
style: {
|
|
498
|
-
stroke: isLeadingEdge ? c.edgeActive : c.edgeExecuted,
|
|
499
|
-
strokeWidth: 3.5
|
|
500
|
-
},
|
|
501
|
-
labelStyle: { fontSize: 10, fontWeight: 600, fill: c.labelExecuted },
|
|
502
|
-
animated: !!isLeadingEdge,
|
|
503
|
-
zIndex: 1
|
|
504
|
-
});
|
|
505
|
-
} else {
|
|
506
|
-
state.edges.push({
|
|
507
|
-
id: `se${state.edgeCounter}`,
|
|
508
|
-
source,
|
|
509
|
-
target,
|
|
510
|
-
label,
|
|
511
|
-
style: {
|
|
512
|
-
stroke: c.edgeDefault,
|
|
513
|
-
strokeWidth: 1.5,
|
|
514
|
-
opacity: o ? 0.3 : 1
|
|
515
|
-
},
|
|
516
|
-
labelStyle: { fontSize: 10, fill: c.labelDefault }
|
|
517
|
-
});
|
|
696
|
+
function registerNode(state, node) {
|
|
697
|
+
if (node.id && node.name) {
|
|
698
|
+
state.idToName.set(node.id, node.name);
|
|
518
699
|
}
|
|
519
700
|
}
|
|
520
|
-
function
|
|
701
|
+
function walkLayout(node, state, x, y) {
|
|
702
|
+
if (!node) return { lastIds: [], bottomY: y };
|
|
703
|
+
registerNode(state, node);
|
|
521
704
|
const id = nid(node);
|
|
522
705
|
if (state.seen.has(id)) {
|
|
523
706
|
return { lastIds: [id], bottomY: y };
|
|
524
707
|
}
|
|
525
708
|
state.seen.add(id);
|
|
526
|
-
const isDecider = node.type === "decider" || node.hasDecider;
|
|
709
|
+
const isDecider = node.type === "decider" || !!node.hasDecider;
|
|
527
710
|
const isFork = node.type === "fork";
|
|
528
|
-
const o = state.overlay;
|
|
529
|
-
const isDone = o ? o.doneStages.has(id) : false;
|
|
530
|
-
const isActive = o ? o.activeStage === id : false;
|
|
531
|
-
const wasExecuted = o ? o.executedStages.has(id) : false;
|
|
532
|
-
const dimmed = o && !wasExecuted;
|
|
533
|
-
let stepNumbers;
|
|
534
|
-
if (o?.executionOrder) {
|
|
535
|
-
const nums = [];
|
|
536
|
-
for (let i = 0; i < o.executionOrder.length; i++) {
|
|
537
|
-
if (o.executionOrder[i] === id) nums.push(i + 1);
|
|
538
|
-
}
|
|
539
|
-
if (nums.length > 0) stepNumbers = nums;
|
|
540
|
-
}
|
|
541
711
|
state.nodes.push({
|
|
542
712
|
id,
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
dimmed,
|
|
554
|
-
stepNumbers,
|
|
555
|
-
isSubflow: !!node.isSubflowRoot
|
|
556
|
-
},
|
|
557
|
-
type: "stage",
|
|
558
|
-
style: dimmed ? { opacity: 0.35 } : void 0
|
|
713
|
+
x,
|
|
714
|
+
y,
|
|
715
|
+
label: node.name,
|
|
716
|
+
isDecider,
|
|
717
|
+
isFork,
|
|
718
|
+
description: node.description,
|
|
719
|
+
icon: node.icon,
|
|
720
|
+
subflowId: node.subflowId,
|
|
721
|
+
isSubflow: !!node.isSubflowRoot,
|
|
722
|
+
isLazy: node.isLazy
|
|
559
723
|
});
|
|
560
724
|
let lastIds = [id];
|
|
561
725
|
let bottomY = y;
|
|
@@ -566,120 +730,257 @@ function walk(node, state, x, y) {
|
|
|
566
730
|
const childResults = [];
|
|
567
731
|
for (let i = 0; i < node.children.length; i++) {
|
|
568
732
|
const child = node.children[i];
|
|
733
|
+
if (!child) continue;
|
|
569
734
|
const childX = startX + i * X_SPREAD;
|
|
570
735
|
const edgeLabel = node.branchIds?.[i];
|
|
571
|
-
|
|
572
|
-
|
|
736
|
+
state.edgeCounter++;
|
|
737
|
+
state.edges.push({ id: `se${state.edgeCounter}`, source: id, target: nid(child), label: edgeLabel, isLoop: false });
|
|
738
|
+
const result = walkLayout(child, state, childX, childY);
|
|
573
739
|
childResults.push(result);
|
|
574
740
|
}
|
|
575
741
|
lastIds = childResults.flatMap((r) => r.lastIds);
|
|
576
742
|
bottomY = Math.max(...childResults.map((r) => r.bottomY));
|
|
577
743
|
}
|
|
578
744
|
if (node.loopTarget) {
|
|
579
|
-
|
|
745
|
+
const resolvedTarget = state.idToName.get(node.loopTarget) ?? node.loopTarget;
|
|
746
|
+
state.edgeCounter++;
|
|
747
|
+
state.edges.push({ id: `se${state.edgeCounter}`, source: id, target: resolvedTarget, label: "loop", isLoop: true });
|
|
580
748
|
}
|
|
581
749
|
if (node.next) {
|
|
750
|
+
const rawNextId = nid(node.next);
|
|
751
|
+
const resolvedNextId = state.idToName.get(rawNextId) ?? rawNextId;
|
|
752
|
+
const isLoopRef = node.loopTarget && state.seen.has(resolvedNextId);
|
|
753
|
+
if (isLoopRef) {
|
|
754
|
+
return { lastIds, bottomY };
|
|
755
|
+
}
|
|
582
756
|
const nextY = bottomY + Y_STEP;
|
|
583
|
-
const nextId = nid(node.next);
|
|
584
757
|
for (const lid of lastIds) {
|
|
585
|
-
|
|
586
|
-
|
|
758
|
+
state.edgeCounter++;
|
|
759
|
+
state.edges.push({ id: `se${state.edgeCounter}`, source: lid, target: resolvedNextId, isLoop: false });
|
|
587
760
|
}
|
|
588
|
-
|
|
589
|
-
return result;
|
|
761
|
+
return walkLayout(node.next, state, x, nextY);
|
|
590
762
|
}
|
|
591
763
|
return { lastIds, bottomY };
|
|
592
764
|
}
|
|
593
|
-
function
|
|
765
|
+
function specToLayout(spec) {
|
|
594
766
|
const state = {
|
|
595
767
|
nodes: [],
|
|
596
768
|
edges: [],
|
|
597
769
|
edgeCounter: 0,
|
|
598
770
|
seen: /* @__PURE__ */ new Set(),
|
|
599
|
-
|
|
600
|
-
colors: { ...DEFAULT_COLORS, ...colors }
|
|
771
|
+
idToName: /* @__PURE__ */ new Map()
|
|
601
772
|
};
|
|
602
|
-
|
|
603
|
-
return { nodes: state.nodes, edges: state.edges };
|
|
773
|
+
walkLayout(spec, state, 300, 0);
|
|
774
|
+
return { nodes: state.nodes, edges: state.edges, idToName: state.idToName };
|
|
604
775
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
function collectSubflows(node) {
|
|
619
|
-
if (node.isSubflowRoot && node.subflowStructure) {
|
|
620
|
-
const id = node.name || node.id || "";
|
|
621
|
-
map.set(id, node);
|
|
776
|
+
function applyOverlay(layout, overlay, colors) {
|
|
777
|
+
const c = { ...DEFAULT_COLORS, ...colors };
|
|
778
|
+
const o = overlay ?? null;
|
|
779
|
+
const nodes = layout.nodes.map((ln) => {
|
|
780
|
+
const isDone = o ? o.doneStages.has(ln.id) : false;
|
|
781
|
+
const isActive = o ? o.activeStage === ln.id : false;
|
|
782
|
+
const wasExecuted = o ? o.executedStages.has(ln.id) : false;
|
|
783
|
+
const dimmed = o && !wasExecuted;
|
|
784
|
+
let stepNumbers;
|
|
785
|
+
if (o?.executionOrder) {
|
|
786
|
+
const nums = [];
|
|
787
|
+
for (let i = 0; i < o.executionOrder.length; i++) {
|
|
788
|
+
if (o.executionOrder[i] === ln.id) nums.push(i + 1);
|
|
622
789
|
}
|
|
623
|
-
if (
|
|
624
|
-
if (node.next) collectSubflows(node.next);
|
|
790
|
+
if (nums.length > 0) stepNumbers = nums;
|
|
625
791
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
792
|
+
return {
|
|
793
|
+
id: ln.id,
|
|
794
|
+
position: { x: ln.x, y: ln.y },
|
|
795
|
+
data: {
|
|
796
|
+
label: ln.label,
|
|
797
|
+
active: isActive,
|
|
798
|
+
done: isDone,
|
|
799
|
+
error: false,
|
|
800
|
+
isDecider: ln.isDecider,
|
|
801
|
+
isFork: ln.isFork,
|
|
802
|
+
description: ln.description,
|
|
803
|
+
icon: ln.icon,
|
|
804
|
+
subflowId: ln.subflowId,
|
|
805
|
+
dimmed,
|
|
806
|
+
stepNumbers,
|
|
807
|
+
isSubflow: ln.isSubflow,
|
|
808
|
+
isLazy: ln.isLazy
|
|
809
|
+
},
|
|
810
|
+
type: "stage",
|
|
811
|
+
style: dimmed ? { opacity: 0.35 } : void 0
|
|
634
812
|
};
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
const
|
|
638
|
-
(
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
description: subflowNode.description
|
|
813
|
+
});
|
|
814
|
+
const edges = [];
|
|
815
|
+
for (const le of layout.edges) {
|
|
816
|
+
const executed = o && o.executedStages.has(le.source) && o.executedStages.has(le.target);
|
|
817
|
+
const isLeadingEdge = o && le.source === o.activeStage && !o.doneStages.has(le.target);
|
|
818
|
+
if (le.isLoop) {
|
|
819
|
+
let loopExecuted = false;
|
|
820
|
+
if (o?.executionOrder) {
|
|
821
|
+
const lastSourceIdx = o.executionOrder.lastIndexOf(le.source);
|
|
822
|
+
if (lastSourceIdx >= 0) {
|
|
823
|
+
loopExecuted = o.executionOrder.slice(lastSourceIdx + 1).includes(le.target);
|
|
647
824
|
}
|
|
648
|
-
]);
|
|
649
|
-
return true;
|
|
650
|
-
},
|
|
651
|
-
[subflowMap]
|
|
652
|
-
);
|
|
653
|
-
const navigateTo = (0, import_react6.useCallback)(
|
|
654
|
-
(level) => {
|
|
655
|
-
if (level === 0) {
|
|
656
|
-
setStack([]);
|
|
657
|
-
} else {
|
|
658
|
-
setStack((prev) => prev.slice(0, level));
|
|
659
825
|
}
|
|
826
|
+
edges.push({
|
|
827
|
+
id: le.id,
|
|
828
|
+
source: le.source,
|
|
829
|
+
target: le.target,
|
|
830
|
+
sourceHandle: "loop-source",
|
|
831
|
+
targetHandle: "loop-target",
|
|
832
|
+
label: le.label ?? "loop",
|
|
833
|
+
type: "smoothstep",
|
|
834
|
+
pathOptions: { offset: 40, borderRadius: 16 },
|
|
835
|
+
style: {
|
|
836
|
+
stroke: c.edgeLoop,
|
|
837
|
+
strokeWidth: loopExecuted ? 3 : 2,
|
|
838
|
+
strokeDasharray: "6 3",
|
|
839
|
+
opacity: o && !loopExecuted ? 0.35 : 1
|
|
840
|
+
},
|
|
841
|
+
labelStyle: { fontSize: 10, fontWeight: 700, fill: c.labelLoop },
|
|
842
|
+
animated: loopExecuted,
|
|
843
|
+
zIndex: 2
|
|
844
|
+
});
|
|
845
|
+
} else if (executed) {
|
|
846
|
+
edges.push({
|
|
847
|
+
id: `${le.id}-glow`,
|
|
848
|
+
source: le.source,
|
|
849
|
+
target: le.target,
|
|
850
|
+
style: { stroke: c.pathGlow, strokeWidth: 8, opacity: 0.4 },
|
|
851
|
+
zIndex: 0,
|
|
852
|
+
selectable: false,
|
|
853
|
+
focusable: false
|
|
854
|
+
});
|
|
855
|
+
edges.push({
|
|
856
|
+
id: le.id,
|
|
857
|
+
source: le.source,
|
|
858
|
+
target: le.target,
|
|
859
|
+
label: le.label,
|
|
860
|
+
style: {
|
|
861
|
+
stroke: isLeadingEdge ? c.edgeActive : c.edgeExecuted,
|
|
862
|
+
strokeWidth: 3.5
|
|
863
|
+
},
|
|
864
|
+
labelStyle: { fontSize: 10, fontWeight: 600, fill: c.labelExecuted },
|
|
865
|
+
animated: !!isLeadingEdge,
|
|
866
|
+
zIndex: 1
|
|
867
|
+
});
|
|
868
|
+
} else {
|
|
869
|
+
edges.push({
|
|
870
|
+
id: le.id,
|
|
871
|
+
source: le.source,
|
|
872
|
+
target: le.target,
|
|
873
|
+
label: le.label,
|
|
874
|
+
style: {
|
|
875
|
+
stroke: c.edgeDefault,
|
|
876
|
+
strokeWidth: 1.5,
|
|
877
|
+
opacity: o ? 0.3 : 1
|
|
878
|
+
},
|
|
879
|
+
labelStyle: { fontSize: 10, fill: c.labelDefault }
|
|
880
|
+
});
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
return { nodes, edges };
|
|
884
|
+
}
|
|
885
|
+
function specToReactFlow(spec, overlay, colors) {
|
|
886
|
+
const layout = specToLayout(spec);
|
|
887
|
+
return applyOverlay(layout, overlay, colors);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// src/components/FlowchartView/TracedFlowchartView.tsx
|
|
891
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
892
|
+
var defaultNodeTypes = { stage: StageNode };
|
|
893
|
+
function FitViewOnResize() {
|
|
894
|
+
const { fitView } = (0, import_react8.useReactFlow)();
|
|
895
|
+
(0, import_react7.useEffect)(() => {
|
|
896
|
+
const handler = () => {
|
|
897
|
+
requestAnimationFrame(() => fitView({ padding: 0.3 }));
|
|
898
|
+
};
|
|
899
|
+
window.addEventListener("resize", handler);
|
|
900
|
+
return () => window.removeEventListener("resize", handler);
|
|
901
|
+
}, [fitView]);
|
|
902
|
+
return null;
|
|
903
|
+
}
|
|
904
|
+
function TracedFlowchartView({
|
|
905
|
+
spec,
|
|
906
|
+
snapshots,
|
|
907
|
+
snapshotIndex = 0,
|
|
908
|
+
onNodeClick,
|
|
909
|
+
nodeTypes: customNodeTypes,
|
|
910
|
+
unstyled = false,
|
|
911
|
+
className,
|
|
912
|
+
style
|
|
913
|
+
}) {
|
|
914
|
+
const nodeTypes2 = customNodeTypes ?? defaultNodeTypes;
|
|
915
|
+
const overlay = (0, import_react7.useMemo)(() => {
|
|
916
|
+
if (!snapshots || snapshots.length === 0) return void 0;
|
|
917
|
+
const executionOrder = snapshots.slice(0, snapshotIndex + 1).map((s) => s.stageLabel);
|
|
918
|
+
const doneStages = new Set(
|
|
919
|
+
snapshots.slice(0, snapshotIndex).map((s) => s.stageLabel)
|
|
920
|
+
);
|
|
921
|
+
const activeStage = snapshots[snapshotIndex]?.stageLabel ?? null;
|
|
922
|
+
const executedStages = /* @__PURE__ */ new Set([...doneStages]);
|
|
923
|
+
if (activeStage) executedStages.add(activeStage);
|
|
924
|
+
return { doneStages, activeStage, executedStages, executionOrder };
|
|
925
|
+
}, [snapshots, snapshotIndex]);
|
|
926
|
+
const layout = (0, import_react7.useMemo)(() => {
|
|
927
|
+
if (!spec) return null;
|
|
928
|
+
return specToLayout(spec);
|
|
929
|
+
}, [spec]);
|
|
930
|
+
const { nodes, edges } = (0, import_react7.useMemo)(() => {
|
|
931
|
+
if (!layout) return { nodes: [], edges: [] };
|
|
932
|
+
return applyOverlay(layout, overlay);
|
|
933
|
+
}, [layout, overlay]);
|
|
934
|
+
const handleNodeClick = (0, import_react7.useCallback)(
|
|
935
|
+
(_, node) => {
|
|
936
|
+
if (!onNodeClick) return;
|
|
937
|
+
onNodeClick(node.id);
|
|
660
938
|
},
|
|
661
|
-
[]
|
|
939
|
+
[onNodeClick]
|
|
940
|
+
);
|
|
941
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
942
|
+
"div",
|
|
943
|
+
{
|
|
944
|
+
className,
|
|
945
|
+
style: { width: "100%", height: "100%", ...style },
|
|
946
|
+
"data-fp": "traced-flowchart",
|
|
947
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
948
|
+
import_react8.ReactFlow,
|
|
949
|
+
{
|
|
950
|
+
nodes,
|
|
951
|
+
edges,
|
|
952
|
+
onNodeClick: handleNodeClick,
|
|
953
|
+
nodeTypes: nodeTypes2,
|
|
954
|
+
fitView: true,
|
|
955
|
+
fitViewOptions: { padding: 0.3 },
|
|
956
|
+
proOptions: { hideAttribution: true },
|
|
957
|
+
panOnDrag: false,
|
|
958
|
+
zoomOnScroll: false,
|
|
959
|
+
zoomOnPinch: false,
|
|
960
|
+
zoomOnDoubleClick: false,
|
|
961
|
+
preventScrolling: false,
|
|
962
|
+
nodesDraggable: false,
|
|
963
|
+
nodesConnectable: false,
|
|
964
|
+
elementsSelectable: !!onNodeClick,
|
|
965
|
+
children: [
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FitViewOnResize, {}),
|
|
967
|
+
!unstyled && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react8.Background, { variant: import_react8.BackgroundVariant.Dots, gap: 16, size: 1 })
|
|
968
|
+
]
|
|
969
|
+
}
|
|
970
|
+
)
|
|
971
|
+
}
|
|
662
972
|
);
|
|
663
|
-
return {
|
|
664
|
-
breadcrumbs,
|
|
665
|
-
nodes,
|
|
666
|
-
edges,
|
|
667
|
-
handleNodeClick,
|
|
668
|
-
navigateTo,
|
|
669
|
-
isInSubflow: stack.length > 0,
|
|
670
|
-
currentSubflowNodeName: stack.length > 0 ? stack[stack.length - 1].label : null
|
|
671
|
-
};
|
|
672
973
|
}
|
|
673
974
|
|
|
674
975
|
// src/components/FlowchartView/SubflowBreadcrumb.tsx
|
|
675
|
-
var
|
|
676
|
-
var
|
|
677
|
-
var SubflowBreadcrumb = (0,
|
|
976
|
+
var import_react9 = require("react");
|
|
977
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
978
|
+
var SubflowBreadcrumb = (0, import_react9.memo)(function SubflowBreadcrumb2({
|
|
678
979
|
breadcrumbs,
|
|
679
980
|
onNavigate
|
|
680
981
|
}) {
|
|
681
982
|
if (breadcrumbs.length <= 1) return null;
|
|
682
|
-
return /* @__PURE__ */ (0,
|
|
983
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
683
984
|
"div",
|
|
684
985
|
{
|
|
685
986
|
style: {
|
|
@@ -696,10 +997,10 @@ var SubflowBreadcrumb = (0, import_react7.memo)(function SubflowBreadcrumb2({
|
|
|
696
997
|
},
|
|
697
998
|
children: breadcrumbs.map((crumb, i) => {
|
|
698
999
|
const isLast = i === breadcrumbs.length - 1;
|
|
699
|
-
return /* @__PURE__ */ (0,
|
|
700
|
-
i > 0 && /* @__PURE__ */ (0,
|
|
701
|
-
isLast ? /* @__PURE__ */ (0,
|
|
702
|
-
/* @__PURE__ */ (0,
|
|
1000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
1001
|
+
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" }),
|
|
1002
|
+
isLast ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
1003
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
703
1004
|
"span",
|
|
704
1005
|
{
|
|
705
1006
|
style: {
|
|
@@ -709,7 +1010,7 @@ var SubflowBreadcrumb = (0, import_react7.memo)(function SubflowBreadcrumb2({
|
|
|
709
1010
|
children: crumb.label
|
|
710
1011
|
}
|
|
711
1012
|
),
|
|
712
|
-
crumb.description && /* @__PURE__ */ (0,
|
|
1013
|
+
crumb.description && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
713
1014
|
"span",
|
|
714
1015
|
{
|
|
715
1016
|
style: {
|
|
@@ -723,7 +1024,7 @@ var SubflowBreadcrumb = (0, import_react7.memo)(function SubflowBreadcrumb2({
|
|
|
723
1024
|
]
|
|
724
1025
|
}
|
|
725
1026
|
)
|
|
726
|
-
] }) : /* @__PURE__ */ (0,
|
|
1027
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
727
1028
|
"button",
|
|
728
1029
|
{
|
|
729
1030
|
onClick: () => onNavigate(i),
|
|
@@ -754,13 +1055,83 @@ var SubflowBreadcrumb = (0, import_react7.memo)(function SubflowBreadcrumb2({
|
|
|
754
1055
|
);
|
|
755
1056
|
});
|
|
756
1057
|
|
|
1058
|
+
// src/components/FlowchartView/useSubflowNavigation.ts
|
|
1059
|
+
var import_react10 = require("react");
|
|
1060
|
+
function useSubflowNavigation(rootSpec, overlay, colors) {
|
|
1061
|
+
const [stack, setStack] = (0, import_react10.useState)([]);
|
|
1062
|
+
const currentSpec = stack.length > 0 ? stack[stack.length - 1].spec : rootSpec;
|
|
1063
|
+
const { nodes, edges } = (0, import_react10.useMemo)(() => {
|
|
1064
|
+
if (!currentSpec) return { nodes: [], edges: [] };
|
|
1065
|
+
return specToReactFlow(currentSpec, overlay, colors);
|
|
1066
|
+
}, [currentSpec, overlay, colors]);
|
|
1067
|
+
const subflowMap = (0, import_react10.useMemo)(() => {
|
|
1068
|
+
const map = /* @__PURE__ */ new Map();
|
|
1069
|
+
if (!currentSpec) return map;
|
|
1070
|
+
function collectSubflows(node) {
|
|
1071
|
+
if (node.isSubflowRoot && node.subflowStructure) {
|
|
1072
|
+
const id = node.name || node.id || "";
|
|
1073
|
+
map.set(id, node);
|
|
1074
|
+
}
|
|
1075
|
+
if (node.children) node.children.forEach(collectSubflows);
|
|
1076
|
+
if (node.next) collectSubflows(node.next);
|
|
1077
|
+
}
|
|
1078
|
+
collectSubflows(currentSpec);
|
|
1079
|
+
return map;
|
|
1080
|
+
}, [currentSpec]);
|
|
1081
|
+
const breadcrumbs = (0, import_react10.useMemo)(() => {
|
|
1082
|
+
const root = {
|
|
1083
|
+
label: rootSpec?.name || "Flowchart",
|
|
1084
|
+
spec: rootSpec,
|
|
1085
|
+
description: rootSpec?.description
|
|
1086
|
+
};
|
|
1087
|
+
return [root, ...stack];
|
|
1088
|
+
}, [rootSpec, stack]);
|
|
1089
|
+
const handleNodeClick = (0, import_react10.useCallback)(
|
|
1090
|
+
(nodeId) => {
|
|
1091
|
+
const subflowNode = subflowMap.get(nodeId);
|
|
1092
|
+
if (!subflowNode?.subflowStructure) return false;
|
|
1093
|
+
setStack((prev) => [
|
|
1094
|
+
...prev,
|
|
1095
|
+
{
|
|
1096
|
+
label: subflowNode.subflowName || subflowNode.name,
|
|
1097
|
+
spec: subflowNode.subflowStructure,
|
|
1098
|
+
description: subflowNode.description
|
|
1099
|
+
}
|
|
1100
|
+
]);
|
|
1101
|
+
return true;
|
|
1102
|
+
},
|
|
1103
|
+
[subflowMap]
|
|
1104
|
+
);
|
|
1105
|
+
const navigateTo = (0, import_react10.useCallback)(
|
|
1106
|
+
(level) => {
|
|
1107
|
+
if (level === 0) {
|
|
1108
|
+
setStack([]);
|
|
1109
|
+
} else {
|
|
1110
|
+
setStack((prev) => prev.slice(0, level));
|
|
1111
|
+
}
|
|
1112
|
+
},
|
|
1113
|
+
[]
|
|
1114
|
+
);
|
|
1115
|
+
return {
|
|
1116
|
+
breadcrumbs,
|
|
1117
|
+
nodes,
|
|
1118
|
+
edges,
|
|
1119
|
+
handleNodeClick,
|
|
1120
|
+
navigateTo,
|
|
1121
|
+
isInSubflow: stack.length > 0,
|
|
1122
|
+
currentSubflowNodeName: stack.length > 0 ? stack[stack.length - 1].label : null
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
|
|
757
1126
|
// src/components/FlowchartView/SubflowTree.tsx
|
|
758
|
-
var
|
|
759
|
-
var
|
|
1127
|
+
var import_react11 = require("react");
|
|
1128
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
760
1129
|
function specToTree(node) {
|
|
1130
|
+
if (!node) return [];
|
|
761
1131
|
const entries = [];
|
|
762
1132
|
const seen = /* @__PURE__ */ new Set();
|
|
763
|
-
function
|
|
1133
|
+
function walk(n) {
|
|
1134
|
+
if (!n) return;
|
|
764
1135
|
const id = n.name || n.id || "";
|
|
765
1136
|
if (seen.has(id)) return;
|
|
766
1137
|
seen.add(id);
|
|
@@ -776,35 +1147,35 @@ function specToTree(node) {
|
|
|
776
1147
|
entries.push(entry);
|
|
777
1148
|
if (n.children) {
|
|
778
1149
|
for (const child of n.children) {
|
|
779
|
-
|
|
1150
|
+
if (child) walk(child);
|
|
780
1151
|
}
|
|
781
1152
|
}
|
|
782
1153
|
if (n.next) {
|
|
783
|
-
|
|
1154
|
+
walk(n.next);
|
|
784
1155
|
}
|
|
785
1156
|
}
|
|
786
|
-
|
|
1157
|
+
walk(node);
|
|
787
1158
|
return entries;
|
|
788
1159
|
}
|
|
789
|
-
var TreeNode = (0,
|
|
1160
|
+
var TreeNode = (0, import_react11.memo)(function TreeNode2({
|
|
790
1161
|
entry,
|
|
791
1162
|
depth,
|
|
792
1163
|
activeStage,
|
|
793
1164
|
doneStages,
|
|
794
1165
|
onNodeSelect
|
|
795
1166
|
}) {
|
|
796
|
-
const [expanded, setExpanded] = (0,
|
|
1167
|
+
const [expanded, setExpanded] = (0, import_react11.useState)(true);
|
|
797
1168
|
const hasChildren = entry.children && entry.children.length > 0;
|
|
798
1169
|
const isActive = activeStage === entry.name;
|
|
799
1170
|
const isDone = doneStages?.has(entry.name);
|
|
800
|
-
const handleClick = (0,
|
|
1171
|
+
const handleClick = (0, import_react11.useCallback)(() => {
|
|
801
1172
|
if (hasChildren) {
|
|
802
1173
|
setExpanded((prev) => !prev);
|
|
803
1174
|
}
|
|
804
1175
|
onNodeSelect?.(entry.name, !!entry.isSubflow);
|
|
805
1176
|
}, [hasChildren, onNodeSelect, entry.name, entry.isSubflow]);
|
|
806
|
-
return /* @__PURE__ */ (0,
|
|
807
|
-
/* @__PURE__ */ (0,
|
|
1177
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1178
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
808
1179
|
"button",
|
|
809
1180
|
{
|
|
810
1181
|
onClick: handleClick,
|
|
@@ -835,7 +1206,7 @@ var TreeNode = (0, import_react8.memo)(function TreeNode2({
|
|
|
835
1206
|
}
|
|
836
1207
|
},
|
|
837
1208
|
children: [
|
|
838
|
-
hasChildren ? /* @__PURE__ */ (0,
|
|
1209
|
+
hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
839
1210
|
"span",
|
|
840
1211
|
{
|
|
841
1212
|
style: {
|
|
@@ -850,8 +1221,8 @@ var TreeNode = (0, import_react8.memo)(function TreeNode2({
|
|
|
850
1221
|
},
|
|
851
1222
|
children: "\u25B6"
|
|
852
1223
|
}
|
|
853
|
-
) : /* @__PURE__ */ (0,
|
|
854
|
-
/* @__PURE__ */ (0,
|
|
1224
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { width: 12, flexShrink: 0 } }),
|
|
1225
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
855
1226
|
"span",
|
|
856
1227
|
{
|
|
857
1228
|
style: {
|
|
@@ -863,8 +1234,8 @@ var TreeNode = (0, import_react8.memo)(function TreeNode2({
|
|
|
863
1234
|
}
|
|
864
1235
|
}
|
|
865
1236
|
),
|
|
866
|
-
/* @__PURE__ */ (0,
|
|
867
|
-
/* @__PURE__ */ (0,
|
|
1237
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
|
|
1238
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
868
1239
|
"span",
|
|
869
1240
|
{
|
|
870
1241
|
style: {
|
|
@@ -876,11 +1247,11 @@ var TreeNode = (0, import_react8.memo)(function TreeNode2({
|
|
|
876
1247
|
},
|
|
877
1248
|
children: [
|
|
878
1249
|
entry.name,
|
|
879
|
-
entry.isSubflow && /* @__PURE__ */ (0,
|
|
1250
|
+
entry.isSubflow && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { opacity: 0.5, marginLeft: 4, fontSize: 10 }, children: "\u229E" })
|
|
880
1251
|
]
|
|
881
1252
|
}
|
|
882
1253
|
),
|
|
883
|
-
entry.description && /* @__PURE__ */ (0,
|
|
1254
|
+
entry.description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
884
1255
|
"span",
|
|
885
1256
|
{
|
|
886
1257
|
style: {
|
|
@@ -897,7 +1268,7 @@ var TreeNode = (0, import_react8.memo)(function TreeNode2({
|
|
|
897
1268
|
]
|
|
898
1269
|
}
|
|
899
1270
|
),
|
|
900
|
-
hasChildren && expanded && /* @__PURE__ */ (0,
|
|
1271
|
+
hasChildren && expanded && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { children: entry.children.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
901
1272
|
TreeNode2,
|
|
902
1273
|
{
|
|
903
1274
|
entry: child,
|
|
@@ -906,12 +1277,12 @@ var TreeNode = (0, import_react8.memo)(function TreeNode2({
|
|
|
906
1277
|
doneStages,
|
|
907
1278
|
onNodeSelect
|
|
908
1279
|
},
|
|
909
|
-
`${child.name}-${i}`
|
|
1280
|
+
child.subflowId ?? `${child.name}-${i}`
|
|
910
1281
|
)) })
|
|
911
1282
|
] });
|
|
912
1283
|
});
|
|
913
|
-
var SectionLabel = (0,
|
|
914
|
-
return /* @__PURE__ */ (0,
|
|
1284
|
+
var SectionLabel = (0, import_react11.memo)(function SectionLabel2({ children }) {
|
|
1285
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
915
1286
|
"div",
|
|
916
1287
|
{
|
|
917
1288
|
style: {
|
|
@@ -926,7 +1297,7 @@ var SectionLabel = (0, import_react8.memo)(function SectionLabel2({ children })
|
|
|
926
1297
|
}
|
|
927
1298
|
);
|
|
928
1299
|
});
|
|
929
|
-
var SubflowTree = (0,
|
|
1300
|
+
var SubflowTree = (0, import_react11.memo)(function SubflowTree2({
|
|
930
1301
|
spec,
|
|
931
1302
|
activeStage,
|
|
932
1303
|
doneStages,
|
|
@@ -935,21 +1306,10 @@ var SubflowTree = (0, import_react8.memo)(function SubflowTree2({
|
|
|
935
1306
|
className,
|
|
936
1307
|
style
|
|
937
1308
|
}) {
|
|
938
|
-
const tree = (0,
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
TreeNode,
|
|
943
|
-
{
|
|
944
|
-
entry,
|
|
945
|
-
depth: 0,
|
|
946
|
-
activeStage,
|
|
947
|
-
doneStages,
|
|
948
|
-
onNodeSelect
|
|
949
|
-
},
|
|
950
|
-
`${entry.name}-${i}`
|
|
951
|
-
));
|
|
952
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1309
|
+
const tree = (0, import_react11.useMemo)(() => specToTree(spec), [spec]);
|
|
1310
|
+
const subflowStages = (0, import_react11.useMemo)(() => tree.filter((e) => e.isSubflow), [tree]);
|
|
1311
|
+
if (subflowStages.length === 0) return null;
|
|
1312
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
953
1313
|
"div",
|
|
954
1314
|
{
|
|
955
1315
|
className,
|
|
@@ -967,185 +1327,28 @@ var SubflowTree = (0, import_react8.memo)(function SubflowTree2({
|
|
|
967
1327
|
...style
|
|
968
1328
|
},
|
|
969
1329
|
children: [
|
|
970
|
-
!unstyled && /* @__PURE__ */ (0,
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
!unstyled && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { height: 1, background: theme.border, margin: "8px 12px" } }),
|
|
974
|
-
!unstyled && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SectionLabel, { children: "Subflows" }),
|
|
975
|
-
renderEntries(subflowStages)
|
|
976
|
-
] })
|
|
977
|
-
]
|
|
978
|
-
}
|
|
979
|
-
);
|
|
980
|
-
});
|
|
981
|
-
|
|
982
|
-
// src/components/FlowchartView/TracedFlowchartView.tsx
|
|
983
|
-
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
984
|
-
var nodeTypes2 = { stage: StageNode };
|
|
985
|
-
function TracedFlowchartView({
|
|
986
|
-
spec,
|
|
987
|
-
snapshots,
|
|
988
|
-
snapshotIndex = 0,
|
|
989
|
-
onNodeClick,
|
|
990
|
-
onSubflowChange,
|
|
991
|
-
showTree = false,
|
|
992
|
-
treeWidth = 200,
|
|
993
|
-
unstyled = false,
|
|
994
|
-
className,
|
|
995
|
-
style
|
|
996
|
-
}) {
|
|
997
|
-
const [treeVisible, setTreeVisible] = (0, import_react9.useState)(showTree);
|
|
998
|
-
const subflowNav = useSubflowNavigation(spec);
|
|
999
|
-
const currentSpec = subflowNav.breadcrumbs.length > 0 ? subflowNav.breadcrumbs[subflowNav.breadcrumbs.length - 1].spec : null;
|
|
1000
|
-
const overlay = (0, import_react9.useMemo)(() => {
|
|
1001
|
-
if (!snapshots || snapshots.length === 0) return void 0;
|
|
1002
|
-
const executionOrder = snapshots.slice(0, snapshotIndex + 1).map((s) => s.stageLabel);
|
|
1003
|
-
const doneStages = new Set(
|
|
1004
|
-
snapshots.slice(0, snapshotIndex).map((s) => s.stageLabel)
|
|
1005
|
-
);
|
|
1006
|
-
const activeStage = snapshots[snapshotIndex]?.stageLabel ?? null;
|
|
1007
|
-
const executedStages = /* @__PURE__ */ new Set([...doneStages]);
|
|
1008
|
-
if (activeStage) executedStages.add(activeStage);
|
|
1009
|
-
return { doneStages, activeStage, executedStages, executionOrder };
|
|
1010
|
-
}, [snapshots, snapshotIndex]);
|
|
1011
|
-
const { nodes, edges } = (0, import_react9.useMemo)(() => {
|
|
1012
|
-
if (!currentSpec) return { nodes: [], edges: [] };
|
|
1013
|
-
return specToReactFlow(currentSpec, overlay);
|
|
1014
|
-
}, [currentSpec, overlay]);
|
|
1015
|
-
const handleNodeClick = (0, import_react9.useCallback)(
|
|
1016
|
-
(_, node) => {
|
|
1017
|
-
if (subflowNav.handleNodeClick(node.id)) {
|
|
1018
|
-
onSubflowChange?.(true, node.id);
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
if (onNodeClick && snapshots) {
|
|
1022
|
-
const idx = snapshots.findIndex((s) => s.stageLabel === node.id);
|
|
1023
|
-
if (idx >= 0) onNodeClick(idx);
|
|
1024
|
-
} else if (onNodeClick) {
|
|
1025
|
-
onNodeClick(node.id);
|
|
1026
|
-
}
|
|
1027
|
-
},
|
|
1028
|
-
[subflowNav, onNodeClick, onSubflowChange, snapshots]
|
|
1029
|
-
);
|
|
1030
|
-
const handleBreadcrumbNavigate = (0, import_react9.useCallback)(
|
|
1031
|
-
(level) => {
|
|
1032
|
-
subflowNav.navigateTo(level);
|
|
1033
|
-
onSubflowChange?.(level > 0, null);
|
|
1034
|
-
},
|
|
1035
|
-
[subflowNav, onSubflowChange]
|
|
1036
|
-
);
|
|
1037
|
-
const handleTreeNodeSelect = (0, import_react9.useCallback)(
|
|
1038
|
-
(name, isSubflow) => {
|
|
1039
|
-
if (isSubflow) {
|
|
1040
|
-
if (subflowNav.handleNodeClick(name)) {
|
|
1041
|
-
onSubflowChange?.(true, name);
|
|
1042
|
-
}
|
|
1043
|
-
} else if (onNodeClick && snapshots) {
|
|
1044
|
-
const idx = snapshots.findIndex((s) => s.stageLabel === name);
|
|
1045
|
-
if (idx >= 0) onNodeClick(idx);
|
|
1046
|
-
}
|
|
1047
|
-
},
|
|
1048
|
-
[subflowNav, onNodeClick, onSubflowChange, snapshots]
|
|
1049
|
-
);
|
|
1050
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1051
|
-
"div",
|
|
1052
|
-
{
|
|
1053
|
-
className,
|
|
1054
|
-
style: { width: "100%", height: "100%", display: "flex", flexDirection: "row", ...style },
|
|
1055
|
-
"data-fp": "traced-flowchart",
|
|
1056
|
-
children: [
|
|
1057
|
-
showTree && treeVisible && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1058
|
-
SubflowTree,
|
|
1330
|
+
!unstyled && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Subflows" }),
|
|
1331
|
+
subflowStages.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1332
|
+
TreeNode,
|
|
1059
1333
|
{
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
}
|
|
1067
|
-
)
|
|
1068
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { flex: 1, display: "flex", flexDirection: "column", minWidth: 0, height: "100%" }, children: [
|
|
1069
|
-
(subflowNav.isInSubflow || showTree && !treeVisible) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "stretch", flexShrink: 0 }, children: [
|
|
1070
|
-
showTree && !treeVisible && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1071
|
-
"button",
|
|
1072
|
-
{
|
|
1073
|
-
onClick: () => setTreeVisible(true),
|
|
1074
|
-
"data-fp": "tree-toggle",
|
|
1075
|
-
style: unstyled ? {} : {
|
|
1076
|
-
background: "transparent",
|
|
1077
|
-
border: "none",
|
|
1078
|
-
cursor: "pointer",
|
|
1079
|
-
padding: "6px 8px",
|
|
1080
|
-
fontSize: 10,
|
|
1081
|
-
flexShrink: 0
|
|
1082
|
-
},
|
|
1083
|
-
children: "\u25B6"
|
|
1084
|
-
}
|
|
1085
|
-
),
|
|
1086
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1087
|
-
SubflowBreadcrumb,
|
|
1088
|
-
{
|
|
1089
|
-
breadcrumbs: subflowNav.breadcrumbs,
|
|
1090
|
-
onNavigate: handleBreadcrumbNavigate
|
|
1091
|
-
}
|
|
1092
|
-
) })
|
|
1093
|
-
] }),
|
|
1094
|
-
showTree && treeVisible && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "stretch", flexShrink: 0 }, children: [
|
|
1095
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1096
|
-
"button",
|
|
1097
|
-
{
|
|
1098
|
-
onClick: () => setTreeVisible(false),
|
|
1099
|
-
"data-fp": "tree-toggle",
|
|
1100
|
-
style: unstyled ? {} : {
|
|
1101
|
-
background: "transparent",
|
|
1102
|
-
border: "none",
|
|
1103
|
-
cursor: "pointer",
|
|
1104
|
-
padding: "6px 8px",
|
|
1105
|
-
fontSize: 10,
|
|
1106
|
-
flexShrink: 0
|
|
1107
|
-
},
|
|
1108
|
-
children: "\u25C0"
|
|
1109
|
-
}
|
|
1110
|
-
),
|
|
1111
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1 }, children: subflowNav.isInSubflow && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1112
|
-
SubflowBreadcrumb,
|
|
1113
|
-
{
|
|
1114
|
-
breadcrumbs: subflowNav.breadcrumbs,
|
|
1115
|
-
onNavigate: handleBreadcrumbNavigate
|
|
1116
|
-
}
|
|
1117
|
-
) })
|
|
1118
|
-
] }),
|
|
1119
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1120
|
-
import_react10.ReactFlow,
|
|
1121
|
-
{
|
|
1122
|
-
nodes,
|
|
1123
|
-
edges,
|
|
1124
|
-
onNodeClick: handleNodeClick,
|
|
1125
|
-
nodeTypes: nodeTypes2,
|
|
1126
|
-
fitView: true,
|
|
1127
|
-
panOnDrag: false,
|
|
1128
|
-
zoomOnScroll: false,
|
|
1129
|
-
zoomOnPinch: false,
|
|
1130
|
-
zoomOnDoubleClick: false,
|
|
1131
|
-
preventScrolling: false,
|
|
1132
|
-
nodesDraggable: false,
|
|
1133
|
-
nodesConnectable: false,
|
|
1134
|
-
elementsSelectable: !!onNodeClick,
|
|
1135
|
-
children: !unstyled && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react10.Background, { variant: import_react10.BackgroundVariant.Dots, gap: 16, size: 1 })
|
|
1136
|
-
}
|
|
1137
|
-
) })
|
|
1138
|
-
] })
|
|
1334
|
+
entry,
|
|
1335
|
+
depth: 0,
|
|
1336
|
+
activeStage,
|
|
1337
|
+
doneStages,
|
|
1338
|
+
onNodeSelect
|
|
1339
|
+
},
|
|
1340
|
+
entry.subflowId ?? `${entry.name}-${i}`
|
|
1341
|
+
))
|
|
1139
1342
|
]
|
|
1140
1343
|
}
|
|
1141
1344
|
);
|
|
1142
|
-
}
|
|
1345
|
+
});
|
|
1143
1346
|
|
|
1144
1347
|
// src/components/TimeTravelDebugger/TimeTravelDebugger.tsx
|
|
1145
|
-
var
|
|
1348
|
+
var import_react15 = require("react");
|
|
1146
1349
|
|
|
1147
1350
|
// src/components/MemoryInspector/MemoryInspector.tsx
|
|
1148
|
-
var
|
|
1351
|
+
var import_react12 = require("react");
|
|
1149
1352
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1150
1353
|
function MemoryInspector({
|
|
1151
1354
|
data,
|
|
@@ -1158,28 +1361,45 @@ function MemoryInspector({
|
|
|
1158
1361
|
className,
|
|
1159
1362
|
style
|
|
1160
1363
|
}) {
|
|
1161
|
-
const
|
|
1364
|
+
const cacheRef = (0, import_react12.useRef)(null);
|
|
1365
|
+
const { memory, newKeys } = (0, import_react12.useMemo)(() => {
|
|
1162
1366
|
if (data) {
|
|
1163
1367
|
return { memory: data, newKeys: /* @__PURE__ */ new Set() };
|
|
1164
1368
|
}
|
|
1165
1369
|
if (!snapshots || snapshots.length === 0) {
|
|
1166
1370
|
return { memory: {}, newKeys: /* @__PURE__ */ new Set() };
|
|
1167
1371
|
}
|
|
1168
|
-
const
|
|
1169
|
-
|
|
1170
|
-
|
|
1372
|
+
const safeIdx = Math.min(selectedIndex, snapshots.length - 1);
|
|
1373
|
+
let merged;
|
|
1374
|
+
const cache = cacheRef.current;
|
|
1375
|
+
if (cache && cache.snapshots === snapshots && cache.index <= safeIdx) {
|
|
1376
|
+
merged = { ...cache.accumulated };
|
|
1377
|
+
for (let i = cache.index + 1; i <= safeIdx; i++) {
|
|
1378
|
+
Object.assign(merged, snapshots[i]?.memory);
|
|
1379
|
+
}
|
|
1380
|
+
} else {
|
|
1381
|
+
merged = {};
|
|
1382
|
+
for (let i = 0; i <= safeIdx; i++) {
|
|
1383
|
+
Object.assign(merged, snapshots[i]?.memory);
|
|
1384
|
+
}
|
|
1171
1385
|
}
|
|
1386
|
+
cacheRef.current = { snapshots, index: safeIdx, accumulated: merged };
|
|
1172
1387
|
const nk = /* @__PURE__ */ new Set();
|
|
1173
|
-
if (highlightNew &&
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1388
|
+
if (highlightNew && safeIdx > 0) {
|
|
1389
|
+
let prev;
|
|
1390
|
+
if (cache && cache.snapshots === snapshots && cache.index === safeIdx - 1) {
|
|
1391
|
+
prev = cache.accumulated;
|
|
1392
|
+
} else {
|
|
1393
|
+
prev = {};
|
|
1394
|
+
for (let i = 0; i < safeIdx; i++) {
|
|
1395
|
+
Object.assign(prev, snapshots[i]?.memory);
|
|
1396
|
+
}
|
|
1177
1397
|
}
|
|
1178
|
-
const current = snapshots[
|
|
1398
|
+
const current = snapshots[safeIdx]?.memory ?? {};
|
|
1179
1399
|
for (const k of Object.keys(current)) {
|
|
1180
1400
|
if (!(k in prev)) nk.add(k);
|
|
1181
1401
|
}
|
|
1182
|
-
} else if (highlightNew &&
|
|
1402
|
+
} else if (highlightNew && safeIdx === 0 && snapshots[0]) {
|
|
1183
1403
|
for (const k of Object.keys(snapshots[0].memory)) nk.add(k);
|
|
1184
1404
|
}
|
|
1185
1405
|
return { memory: merged, newKeys: nk };
|
|
@@ -1188,9 +1408,9 @@ function MemoryInspector({
|
|
|
1188
1408
|
const fs = fontSize[size];
|
|
1189
1409
|
const pad = padding[size];
|
|
1190
1410
|
if (unstyled) {
|
|
1191
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className, style, "data-fp": "memory-inspector", children: [
|
|
1411
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className, style, "data-fp": "memory-inspector", role: "region", "aria-label": "Memory state", children: [
|
|
1192
1412
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-fp": "memory-label", children: "Memory State" }),
|
|
1193
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-fp": "memory-json", children: JSON.stringify(memory, null, 2) })
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { "data-fp": "memory-json", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { children: JSON.stringify(memory, null, 2) }) })
|
|
1194
1414
|
] });
|
|
1195
1415
|
}
|
|
1196
1416
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
@@ -1203,6 +1423,8 @@ function MemoryInspector({
|
|
|
1203
1423
|
...style
|
|
1204
1424
|
},
|
|
1205
1425
|
"data-fp": "memory-inspector",
|
|
1426
|
+
role: "region",
|
|
1427
|
+
"aria-label": "Memory state",
|
|
1206
1428
|
children: [
|
|
1207
1429
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1208
1430
|
"span",
|
|
@@ -1302,7 +1524,7 @@ function formatValue(value) {
|
|
|
1302
1524
|
}
|
|
1303
1525
|
|
|
1304
1526
|
// src/components/NarrativeLog/NarrativeLog.tsx
|
|
1305
|
-
var
|
|
1527
|
+
var import_react13 = require("react");
|
|
1306
1528
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1307
1529
|
function NarrativeLog({
|
|
1308
1530
|
snapshots,
|
|
@@ -1313,7 +1535,7 @@ function NarrativeLog({
|
|
|
1313
1535
|
className,
|
|
1314
1536
|
style
|
|
1315
1537
|
}) {
|
|
1316
|
-
const entries = (0,
|
|
1538
|
+
const entries = (0, import_react13.useMemo)(() => {
|
|
1317
1539
|
if (narrative) {
|
|
1318
1540
|
return [{ label: "Output", text: narrative, isCurrent: true }];
|
|
1319
1541
|
}
|
|
@@ -1435,7 +1657,7 @@ function NarrativeLog({
|
|
|
1435
1657
|
}
|
|
1436
1658
|
|
|
1437
1659
|
// src/components/GanttTimeline/GanttTimeline.tsx
|
|
1438
|
-
var
|
|
1660
|
+
var import_react14 = require("react");
|
|
1439
1661
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1440
1662
|
function GanttTimeline({
|
|
1441
1663
|
snapshots,
|
|
@@ -1447,10 +1669,10 @@ function GanttTimeline({
|
|
|
1447
1669
|
style,
|
|
1448
1670
|
maxVisibleRows = 5
|
|
1449
1671
|
}) {
|
|
1450
|
-
const [expanded, setExpanded] = (0,
|
|
1451
|
-
const activeRowRef = (0,
|
|
1452
|
-
const scrollContainerRef = (0,
|
|
1453
|
-
const totalWallTime = (0,
|
|
1672
|
+
const [expanded, setExpanded] = (0, import_react14.useState)(false);
|
|
1673
|
+
const activeRowRef = (0, import_react14.useRef)(null);
|
|
1674
|
+
const scrollContainerRef = (0, import_react14.useRef)(null);
|
|
1675
|
+
const totalWallTime = (0, import_react14.useMemo)(
|
|
1454
1676
|
() => Math.max(...snapshots.map((s) => s.startMs + s.durationMs), 1),
|
|
1455
1677
|
[snapshots]
|
|
1456
1678
|
);
|
|
@@ -1461,7 +1683,7 @@ function GanttTimeline({
|
|
|
1461
1683
|
const rowHeight = size === "compact" ? 18 : 22;
|
|
1462
1684
|
const collapsible = maxVisibleRows > 0 && snapshots.length > maxVisibleRows;
|
|
1463
1685
|
const showAll = expanded || !collapsible;
|
|
1464
|
-
(0,
|
|
1686
|
+
(0, import_react14.useEffect)(() => {
|
|
1465
1687
|
if (!showAll && activeRowRef.current && scrollContainerRef.current) {
|
|
1466
1688
|
activeRowRef.current.scrollIntoView({
|
|
1467
1689
|
block: "nearest",
|
|
@@ -1470,12 +1692,15 @@ function GanttTimeline({
|
|
|
1470
1692
|
}
|
|
1471
1693
|
}, [selectedIndex, showAll]);
|
|
1472
1694
|
if (unstyled) {
|
|
1473
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className, style, "data-fp": "gantt-timeline", children: snapshots.map((snap, idx) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1695
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className, style, "data-fp": "gantt-timeline", role: "listbox", "aria-label": "Execution timeline", children: snapshots.map((snap, idx) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1474
1696
|
"div",
|
|
1475
1697
|
{
|
|
1476
1698
|
"data-fp": "gantt-bar",
|
|
1477
1699
|
"data-selected": idx === selectedIndex,
|
|
1478
1700
|
"data-visible": idx <= selectedIndex,
|
|
1701
|
+
role: "option",
|
|
1702
|
+
"aria-selected": idx === selectedIndex,
|
|
1703
|
+
"aria-label": `${snap.stageLabel}, ${snap.durationMs}ms`,
|
|
1479
1704
|
onClick: () => onSelect?.(idx),
|
|
1480
1705
|
children: [
|
|
1481
1706
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-fp": "gantt-label", children: snap.stageLabel }),
|
|
@@ -1485,7 +1710,7 @@ function GanttTimeline({
|
|
|
1485
1710
|
] })
|
|
1486
1711
|
]
|
|
1487
1712
|
},
|
|
1488
|
-
snap.stageName
|
|
1713
|
+
`${snap.stageName}-${idx}`
|
|
1489
1714
|
)) });
|
|
1490
1715
|
}
|
|
1491
1716
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
@@ -1541,6 +1766,8 @@ function GanttTimeline({
|
|
|
1541
1766
|
"div",
|
|
1542
1767
|
{
|
|
1543
1768
|
ref: scrollContainerRef,
|
|
1769
|
+
role: "listbox",
|
|
1770
|
+
"aria-label": "Execution timeline",
|
|
1544
1771
|
style: {
|
|
1545
1772
|
marginTop: 8,
|
|
1546
1773
|
display: "flex",
|
|
@@ -1561,6 +1788,9 @@ function GanttTimeline({
|
|
|
1561
1788
|
"div",
|
|
1562
1789
|
{
|
|
1563
1790
|
ref: isSelected ? activeRowRef : void 0,
|
|
1791
|
+
role: "option",
|
|
1792
|
+
"aria-selected": isSelected,
|
|
1793
|
+
"aria-label": `${snap.stageLabel}, ${snap.durationMs}ms`,
|
|
1564
1794
|
onClick: () => onSelect?.(idx),
|
|
1565
1795
|
style: {
|
|
1566
1796
|
display: "flex",
|
|
@@ -1576,6 +1806,7 @@ function GanttTimeline({
|
|
|
1576
1806
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1577
1807
|
"span",
|
|
1578
1808
|
{
|
|
1809
|
+
title: snap.stageLabel,
|
|
1579
1810
|
style: {
|
|
1580
1811
|
width: labelWidth,
|
|
1581
1812
|
fontSize: fs.small,
|
|
@@ -1635,7 +1866,7 @@ function GanttTimeline({
|
|
|
1635
1866
|
)
|
|
1636
1867
|
]
|
|
1637
1868
|
},
|
|
1638
|
-
snap.stageName
|
|
1869
|
+
`${snap.stageName}-${idx}`
|
|
1639
1870
|
);
|
|
1640
1871
|
})
|
|
1641
1872
|
}
|
|
@@ -1685,7 +1916,7 @@ function TimeTravelDebugger({
|
|
|
1685
1916
|
className,
|
|
1686
1917
|
style
|
|
1687
1918
|
}) {
|
|
1688
|
-
const [selectedIndex, setSelectedIndex] = (0,
|
|
1919
|
+
const [selectedIndex, setSelectedIndex] = (0, import_react15.useState)(0);
|
|
1689
1920
|
const fs = fontSize[size];
|
|
1690
1921
|
const pad = padding[size];
|
|
1691
1922
|
if (snapshots.length === 0) {
|
|
@@ -1990,6 +2221,8 @@ function ScrubButton({
|
|
|
1990
2221
|
SubflowTree,
|
|
1991
2222
|
TimeTravelDebugger,
|
|
1992
2223
|
TracedFlowchartView,
|
|
2224
|
+
applyOverlay,
|
|
2225
|
+
specToLayout,
|
|
1993
2226
|
specToReactFlow,
|
|
1994
2227
|
useSubflowNavigation
|
|
1995
2228
|
});
|