footprint-explainable-ui 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1901 @@
1
+ // src/theme/ThemeProvider.tsx
2
+ import { createContext, useContext } from "react";
3
+
4
+ // src/theme/tokens.ts
5
+ function tokensToCSSVars(tokens) {
6
+ const vars = {};
7
+ if (tokens.colors) {
8
+ const c = tokens.colors;
9
+ if (c.primary) vars["--fp-color-primary"] = c.primary;
10
+ if (c.success) vars["--fp-color-success"] = c.success;
11
+ if (c.error) vars["--fp-color-error"] = c.error;
12
+ if (c.warning) vars["--fp-color-warning"] = c.warning;
13
+ if (c.bgPrimary) vars["--fp-bg-primary"] = c.bgPrimary;
14
+ if (c.bgSecondary) vars["--fp-bg-secondary"] = c.bgSecondary;
15
+ if (c.bgTertiary) vars["--fp-bg-tertiary"] = c.bgTertiary;
16
+ if (c.textPrimary) vars["--fp-text-primary"] = c.textPrimary;
17
+ if (c.textSecondary) vars["--fp-text-secondary"] = c.textSecondary;
18
+ if (c.textMuted) vars["--fp-text-muted"] = c.textMuted;
19
+ if (c.border) vars["--fp-border"] = c.border;
20
+ }
21
+ if (tokens.radius) vars["--fp-radius"] = tokens.radius;
22
+ if (tokens.fontFamily?.sans) vars["--fp-font-sans"] = tokens.fontFamily.sans;
23
+ if (tokens.fontFamily?.mono) vars["--fp-font-mono"] = tokens.fontFamily.mono;
24
+ return vars;
25
+ }
26
+ var defaultTokens = {
27
+ colors: {
28
+ primary: "#6366f1",
29
+ success: "#22c55e",
30
+ error: "#ef4444",
31
+ warning: "#f59e0b",
32
+ bgPrimary: "#0f172a",
33
+ bgSecondary: "#1e293b",
34
+ bgTertiary: "#334155",
35
+ textPrimary: "#f8fafc",
36
+ textSecondary: "#94a3b8",
37
+ textMuted: "#64748b",
38
+ border: "#334155"
39
+ },
40
+ radius: "8px",
41
+ fontFamily: {
42
+ sans: "Inter, system-ui, -apple-system, sans-serif",
43
+ mono: "'JetBrains Mono', 'Fira Code', monospace"
44
+ }
45
+ };
46
+
47
+ // src/theme/ThemeProvider.tsx
48
+ import { jsx } from "react/jsx-runtime";
49
+ var ThemeContext = createContext({});
50
+ function useFootprintTheme() {
51
+ return useContext(ThemeContext);
52
+ }
53
+ function FootprintTheme({ tokens = {}, children }) {
54
+ const cssVars = tokensToCSSVars(tokens);
55
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: tokens, children: /* @__PURE__ */ jsx("div", { style: cssVars, className: "fp-theme-root", children }) });
56
+ }
57
+
58
+ // src/theme/styles.ts
59
+ function v(varName, fallback) {
60
+ return `var(${varName}, ${fallback})`;
61
+ }
62
+ var theme = {
63
+ primary: v("--fp-color-primary", "#6366f1"),
64
+ success: v("--fp-color-success", "#22c55e"),
65
+ error: v("--fp-color-error", "#ef4444"),
66
+ warning: v("--fp-color-warning", "#f59e0b"),
67
+ bgPrimary: v("--fp-bg-primary", "#0f172a"),
68
+ bgSecondary: v("--fp-bg-secondary", "#1e293b"),
69
+ bgTertiary: v("--fp-bg-tertiary", "#334155"),
70
+ textPrimary: v("--fp-text-primary", "#f8fafc"),
71
+ textSecondary: v("--fp-text-secondary", "#94a3b8"),
72
+ textMuted: v("--fp-text-muted", "#64748b"),
73
+ border: v("--fp-border", "#334155"),
74
+ radius: v("--fp-radius", "8px"),
75
+ fontSans: v("--fp-font-sans", "Inter, system-ui, -apple-system, sans-serif"),
76
+ fontMono: v("--fp-font-mono", "'JetBrains Mono', 'Fira Code', monospace")
77
+ };
78
+ var fontSize = {
79
+ compact: { label: 10, body: 11, small: 9 },
80
+ default: { label: 11, body: 12, small: 10 },
81
+ detailed: { label: 12, body: 13, small: 11 }
82
+ };
83
+ var padding = {
84
+ compact: 8,
85
+ default: 12,
86
+ detailed: 16
87
+ };
88
+
89
+ // src/theme/presets.ts
90
+ var coolDark = {
91
+ colors: {
92
+ primary: "#6366f1",
93
+ success: "#22c55e",
94
+ error: "#ef4444",
95
+ warning: "#f59e0b",
96
+ bgPrimary: "#0f172a",
97
+ bgSecondary: "#1e293b",
98
+ bgTertiary: "#334155",
99
+ textPrimary: "#f8fafc",
100
+ textSecondary: "#94a3b8",
101
+ textMuted: "#64748b",
102
+ border: "#334155"
103
+ },
104
+ radius: "8px",
105
+ fontFamily: {
106
+ sans: "Inter, system-ui, -apple-system, sans-serif",
107
+ mono: "'JetBrains Mono', 'Fira Code', monospace"
108
+ }
109
+ };
110
+ var warmDark = {
111
+ colors: {
112
+ primary: "#7c6cf0",
113
+ success: "#3dd68c",
114
+ error: "#f06292",
115
+ warning: "#ffb74d",
116
+ bgPrimary: "#1e1a2e",
117
+ bgSecondary: "#2a2540",
118
+ bgTertiary: "#3a3455",
119
+ textPrimary: "#f0e6d6",
120
+ textSecondary: "#a89eb4",
121
+ textMuted: "#6e6480",
122
+ border: "#3a3455"
123
+ },
124
+ radius: "8px",
125
+ fontFamily: {
126
+ sans: "Inter, system-ui, -apple-system, sans-serif",
127
+ mono: "'JetBrains Mono', 'Fira Code', monospace"
128
+ }
129
+ };
130
+ var warmLight = {
131
+ colors: {
132
+ primary: "#7c6cf0",
133
+ success: "#22a860",
134
+ error: "#d94452",
135
+ warning: "#e09030",
136
+ bgPrimary: "#faf5ef",
137
+ bgSecondary: "#f0e6d6",
138
+ bgTertiary: "#e4d5c3",
139
+ textPrimary: "#2e2938",
140
+ textSecondary: "#5c5468",
141
+ textMuted: "#8a7e96",
142
+ border: "#d6c8b4"
143
+ },
144
+ radius: "8px",
145
+ fontFamily: {
146
+ sans: "Inter, system-ui, -apple-system, sans-serif",
147
+ mono: "'JetBrains Mono', 'Fira Code', monospace"
148
+ }
149
+ };
150
+ var themePresets = {
151
+ coolDark,
152
+ warmDark,
153
+ warmLight
154
+ };
155
+
156
+ // src/components/MemoryInspector/MemoryInspector.tsx
157
+ import { useMemo } from "react";
158
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
159
+ function MemoryInspector({
160
+ data,
161
+ snapshots,
162
+ selectedIndex = 0,
163
+ showTypes = false,
164
+ highlightNew = true,
165
+ size = "default",
166
+ unstyled = false,
167
+ className,
168
+ style
169
+ }) {
170
+ const { memory, newKeys } = useMemo(() => {
171
+ if (data) {
172
+ return { memory: data, newKeys: /* @__PURE__ */ new Set() };
173
+ }
174
+ if (!snapshots || snapshots.length === 0) {
175
+ return { memory: {}, newKeys: /* @__PURE__ */ new Set() };
176
+ }
177
+ const merged = {};
178
+ for (let i = 0; i <= Math.min(selectedIndex, snapshots.length - 1); i++) {
179
+ Object.assign(merged, snapshots[i]?.memory);
180
+ }
181
+ const nk = /* @__PURE__ */ new Set();
182
+ if (highlightNew && selectedIndex > 0) {
183
+ const prev = {};
184
+ for (let i = 0; i < selectedIndex; i++) {
185
+ Object.assign(prev, snapshots[i]?.memory);
186
+ }
187
+ const current = snapshots[selectedIndex]?.memory ?? {};
188
+ for (const k of Object.keys(current)) {
189
+ if (!(k in prev)) nk.add(k);
190
+ }
191
+ } else if (highlightNew && selectedIndex === 0 && snapshots[0]) {
192
+ for (const k of Object.keys(snapshots[0].memory)) nk.add(k);
193
+ }
194
+ return { memory: merged, newKeys: nk };
195
+ }, [data, snapshots, selectedIndex, highlightNew]);
196
+ const entries = Object.entries(memory);
197
+ const fs = fontSize[size];
198
+ const pad = padding[size];
199
+ if (unstyled) {
200
+ return /* @__PURE__ */ jsxs("div", { className, style, "data-fp": "memory-inspector", children: [
201
+ /* @__PURE__ */ jsx2("div", { "data-fp": "memory-label", children: "Memory State" }),
202
+ /* @__PURE__ */ jsx2("pre", { "data-fp": "memory-json", children: JSON.stringify(memory, null, 2) })
203
+ ] });
204
+ }
205
+ return /* @__PURE__ */ jsxs(
206
+ "div",
207
+ {
208
+ className,
209
+ style: {
210
+ padding: pad,
211
+ fontFamily: theme.fontSans,
212
+ ...style
213
+ },
214
+ "data-fp": "memory-inspector",
215
+ children: [
216
+ /* @__PURE__ */ jsx2(
217
+ "span",
218
+ {
219
+ style: {
220
+ fontSize: fs.label,
221
+ fontWeight: 600,
222
+ color: theme.textMuted,
223
+ textTransform: "uppercase",
224
+ letterSpacing: "0.08em"
225
+ },
226
+ children: "Memory State"
227
+ }
228
+ ),
229
+ /* @__PURE__ */ jsxs(
230
+ "div",
231
+ {
232
+ style: {
233
+ marginTop: 8,
234
+ background: theme.bgSecondary,
235
+ border: `1px solid ${theme.border}`,
236
+ borderRadius: theme.radius,
237
+ padding: `${pad}px ${pad + 4}px`,
238
+ fontFamily: theme.fontMono,
239
+ fontSize: fs.body,
240
+ lineHeight: 1.8
241
+ },
242
+ children: [
243
+ /* @__PURE__ */ jsx2("span", { style: { color: theme.textMuted }, children: "{" }),
244
+ entries.length === 0 && /* @__PURE__ */ jsx2(
245
+ "div",
246
+ {
247
+ style: {
248
+ paddingLeft: 16,
249
+ color: theme.textMuted,
250
+ fontStyle: "italic"
251
+ },
252
+ children: "// empty"
253
+ }
254
+ ),
255
+ entries.map(([key, value], i) => {
256
+ const isNew = newKeys.has(key);
257
+ const isLast = i === entries.length - 1;
258
+ return /* @__PURE__ */ jsxs(
259
+ "div",
260
+ {
261
+ style: {
262
+ paddingLeft: 16,
263
+ background: isNew ? `color-mix(in srgb, ${theme.success} 10%, transparent)` : "transparent",
264
+ borderRadius: 4,
265
+ marginLeft: -4,
266
+ marginRight: -4,
267
+ paddingRight: 4
268
+ },
269
+ children: [
270
+ /* @__PURE__ */ jsxs("span", { style: { color: theme.primary }, children: [
271
+ '"',
272
+ key,
273
+ '"'
274
+ ] }),
275
+ /* @__PURE__ */ jsx2("span", { style: { color: theme.textMuted }, children: ": " }),
276
+ /* @__PURE__ */ jsx2("span", { style: { color: theme.success }, children: formatValue(value) }),
277
+ showTypes && /* @__PURE__ */ jsxs(
278
+ "span",
279
+ {
280
+ style: {
281
+ color: theme.textMuted,
282
+ fontSize: fs.small,
283
+ marginLeft: 8,
284
+ opacity: 0.6
285
+ },
286
+ children: [
287
+ "(",
288
+ typeof value,
289
+ ")"
290
+ ]
291
+ }
292
+ ),
293
+ !isLast && /* @__PURE__ */ jsx2("span", { style: { color: theme.textMuted }, children: "," })
294
+ ]
295
+ },
296
+ key
297
+ );
298
+ }),
299
+ /* @__PURE__ */ jsx2("span", { style: { color: theme.textMuted }, children: "}" })
300
+ ]
301
+ }
302
+ )
303
+ ]
304
+ }
305
+ );
306
+ }
307
+ function formatValue(value) {
308
+ if (typeof value === "string") return `"${value}"`;
309
+ if (typeof value === "object" && value !== null) return JSON.stringify(value);
310
+ return String(value);
311
+ }
312
+
313
+ // src/components/NarrativeLog/NarrativeLog.tsx
314
+ import { useMemo as useMemo2 } from "react";
315
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
316
+ function NarrativeLog({
317
+ snapshots,
318
+ selectedIndex,
319
+ narrative,
320
+ size = "default",
321
+ unstyled = false,
322
+ className,
323
+ style
324
+ }) {
325
+ const entries = useMemo2(() => {
326
+ if (narrative) {
327
+ return [{ label: "Output", text: narrative, isCurrent: true }];
328
+ }
329
+ const idx = selectedIndex ?? snapshots.length - 1;
330
+ return snapshots.slice(0, idx + 1).map((s, i) => ({
331
+ label: s.stageLabel,
332
+ text: s.narrative,
333
+ isCurrent: i === idx
334
+ }));
335
+ }, [snapshots, selectedIndex, narrative]);
336
+ const fs = fontSize[size];
337
+ const pad = padding[size];
338
+ if (unstyled) {
339
+ return /* @__PURE__ */ jsx3("div", { className, style, "data-fp": "narrative-log", children: entries.map((entry, i) => /* @__PURE__ */ jsxs2("div", { "data-fp": "narrative-entry", "data-current": entry.isCurrent, children: [
340
+ /* @__PURE__ */ jsx3("strong", { children: entry.label }),
341
+ /* @__PURE__ */ jsx3("p", { children: entry.text })
342
+ ] }, i)) });
343
+ }
344
+ return /* @__PURE__ */ jsxs2(
345
+ "div",
346
+ {
347
+ className,
348
+ style: { padding: pad, fontFamily: theme.fontSans, ...style },
349
+ "data-fp": "narrative-log",
350
+ children: [
351
+ /* @__PURE__ */ jsx3(
352
+ "span",
353
+ {
354
+ style: {
355
+ fontSize: fs.label,
356
+ fontWeight: 600,
357
+ color: theme.textMuted,
358
+ textTransform: "uppercase",
359
+ letterSpacing: "0.08em"
360
+ },
361
+ children: "Execution Log"
362
+ }
363
+ ),
364
+ /* @__PURE__ */ jsx3("div", { style: { marginTop: 8, display: "flex", flexDirection: "column" }, children: entries.map((entry, i) => /* @__PURE__ */ jsxs2(
365
+ "div",
366
+ {
367
+ style: {
368
+ display: "flex",
369
+ gap: 10,
370
+ padding: `${pad}px 0`,
371
+ borderBottom: i < entries.length - 1 ? `1px solid ${theme.border}` : "none"
372
+ },
373
+ children: [
374
+ /* @__PURE__ */ jsxs2(
375
+ "div",
376
+ {
377
+ style: {
378
+ display: "flex",
379
+ flexDirection: "column",
380
+ alignItems: "center",
381
+ width: 12,
382
+ flexShrink: 0,
383
+ paddingTop: 5
384
+ },
385
+ children: [
386
+ /* @__PURE__ */ jsx3(
387
+ "div",
388
+ {
389
+ style: {
390
+ width: 8,
391
+ height: 8,
392
+ borderRadius: "50%",
393
+ background: entry.isCurrent ? theme.primary : theme.success,
394
+ flexShrink: 0
395
+ }
396
+ }
397
+ ),
398
+ i < entries.length - 1 && /* @__PURE__ */ jsx3(
399
+ "div",
400
+ {
401
+ style: {
402
+ width: 1,
403
+ flex: 1,
404
+ background: theme.border,
405
+ marginTop: 4
406
+ }
407
+ }
408
+ )
409
+ ]
410
+ }
411
+ ),
412
+ /* @__PURE__ */ jsxs2("div", { style: { flex: 1, minWidth: 0 }, children: [
413
+ /* @__PURE__ */ jsx3(
414
+ "span",
415
+ {
416
+ style: {
417
+ fontSize: fs.label,
418
+ fontWeight: 600,
419
+ color: entry.isCurrent ? theme.primary : theme.textMuted
420
+ },
421
+ children: entry.label
422
+ }
423
+ ),
424
+ /* @__PURE__ */ jsx3(
425
+ "div",
426
+ {
427
+ style: {
428
+ fontSize: fs.body,
429
+ lineHeight: 1.5,
430
+ color: entry.isCurrent ? theme.textPrimary : theme.textSecondary,
431
+ marginTop: 2
432
+ },
433
+ children: entry.text
434
+ }
435
+ )
436
+ ] })
437
+ ]
438
+ },
439
+ i
440
+ )) })
441
+ ]
442
+ }
443
+ );
444
+ }
445
+
446
+ // src/components/NarrativeTrace/NarrativeTrace.tsx
447
+ import { useState, useCallback, useMemo as useMemo3, useEffect, useRef } from "react";
448
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
449
+ function parseGroups(lines) {
450
+ const groups = [];
451
+ let current = null;
452
+ for (let i = 0; i < lines.length; i++) {
453
+ const line = lines[i];
454
+ const trimmed = line.trimStart();
455
+ const isStep = trimmed.startsWith("Step ") || /^\s/.test(line);
456
+ if (!isStep || !current) {
457
+ current = { header: line, headerIdx: i, steps: [] };
458
+ groups.push(current);
459
+ } else {
460
+ current.steps.push({ text: trimmed, idx: i });
461
+ }
462
+ }
463
+ return groups;
464
+ }
465
+ function NarrativeTrace({
466
+ narrative,
467
+ revealedCount,
468
+ defaultCollapsed = false,
469
+ onStageClick,
470
+ size = "default",
471
+ unstyled = false,
472
+ className,
473
+ style
474
+ }) {
475
+ const revealed = revealedCount != null ? narrative.slice(0, revealedCount) : narrative;
476
+ const future = revealedCount != null ? narrative.slice(revealedCount) : [];
477
+ const revealedGroups = useMemo3(() => parseGroups(revealed), [revealed]);
478
+ const futureGroups = useMemo3(() => parseGroups(future), [future]);
479
+ const [collapsedSet, setCollapsedSet] = useState(() => {
480
+ if (!defaultCollapsed) return /* @__PURE__ */ new Set();
481
+ return new Set(parseGroups(narrative).map((g) => g.headerIdx));
482
+ });
483
+ const latestRef = useRef(null);
484
+ useEffect(() => {
485
+ latestRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" });
486
+ }, [revealedGroups.length]);
487
+ const toggle = useCallback((idx) => {
488
+ setCollapsedSet((prev) => {
489
+ const next = new Set(prev);
490
+ if (next.has(idx)) next.delete(idx);
491
+ else next.add(idx);
492
+ return next;
493
+ });
494
+ }, []);
495
+ const lastIdx = revealedGroups.length - 1;
496
+ const fs = fontSize[size];
497
+ const pad = padding[size];
498
+ if (unstyled) {
499
+ return /* @__PURE__ */ jsxs3("div", { className, style, "data-fp": "narrative-trace", children: [
500
+ revealedGroups.map((group, gi) => /* @__PURE__ */ jsxs3("div", { "data-fp": "narrative-group", "data-latest": gi === lastIdx, children: [
501
+ /* @__PURE__ */ jsx4(
502
+ "div",
503
+ {
504
+ "data-fp": "narrative-header",
505
+ "data-collapsible": group.steps.length > 0,
506
+ "data-collapsed": collapsedSet.has(group.headerIdx),
507
+ onClick: () => {
508
+ if (group.steps.length > 0) toggle(group.headerIdx);
509
+ onStageClick?.(group.headerIdx);
510
+ },
511
+ children: group.header
512
+ }
513
+ ),
514
+ !collapsedSet.has(group.headerIdx) && group.steps.map((step) => /* @__PURE__ */ jsx4("div", { "data-fp": "narrative-step", children: step.text }, step.idx))
515
+ ] }, group.headerIdx)),
516
+ futureGroups.map((group) => /* @__PURE__ */ jsxs3("div", { "data-fp": "narrative-group", "data-future": true, children: [
517
+ /* @__PURE__ */ jsx4("div", { "data-fp": "narrative-header", children: group.header }),
518
+ group.steps.map((step) => /* @__PURE__ */ jsx4("div", { "data-fp": "narrative-step", children: step.text }, `f-${step.idx}`))
519
+ ] }, `f-${group.headerIdx}`))
520
+ ] });
521
+ }
522
+ return /* @__PURE__ */ jsxs3(
523
+ "div",
524
+ {
525
+ className,
526
+ style: {
527
+ flex: 1,
528
+ overflow: "auto",
529
+ padding: pad,
530
+ fontFamily: theme.fontMono,
531
+ ...style
532
+ },
533
+ "data-fp": "narrative-trace",
534
+ children: [
535
+ revealedGroups.map((group, gi) => {
536
+ const isLatest = gi === lastIdx;
537
+ const isCollapsed = collapsedSet.has(group.headerIdx);
538
+ const hasSteps = group.steps.length > 0;
539
+ return /* @__PURE__ */ jsxs3(
540
+ "div",
541
+ {
542
+ ref: isLatest ? latestRef : void 0,
543
+ style: { marginBottom: 2 },
544
+ "data-fp": "narrative-group",
545
+ children: [
546
+ /* @__PURE__ */ jsxs3(
547
+ "div",
548
+ {
549
+ onClick: () => {
550
+ if (hasSteps) toggle(group.headerIdx);
551
+ onStageClick?.(group.headerIdx);
552
+ },
553
+ style: {
554
+ fontSize: fs.body,
555
+ lineHeight: 1.7,
556
+ color: isLatest ? theme.textPrimary : theme.textSecondary,
557
+ padding: `4px ${pad - 4}px`,
558
+ borderRadius: 4,
559
+ background: isLatest ? theme.bgTertiary : "transparent",
560
+ borderLeft: isLatest ? `3px solid ${theme.primary}` : `3px solid ${theme.success}`,
561
+ cursor: hasSteps ? "pointer" : "default",
562
+ fontWeight: 600,
563
+ display: "flex",
564
+ alignItems: "center",
565
+ gap: 6,
566
+ userSelect: "none",
567
+ transition: "all 0.15s ease"
568
+ },
569
+ children: [
570
+ hasSteps && /* @__PURE__ */ jsx4(
571
+ "span",
572
+ {
573
+ style: {
574
+ fontSize: fs.small - 1,
575
+ color: theme.textMuted,
576
+ transition: "transform 0.15s ease",
577
+ transform: isCollapsed ? "rotate(-90deg)" : "rotate(0deg)",
578
+ display: "inline-block",
579
+ width: 10,
580
+ flexShrink: 0
581
+ },
582
+ children: "\u25BC"
583
+ }
584
+ ),
585
+ !hasSteps && /* @__PURE__ */ jsx4("span", { style: { width: 10, flexShrink: 0 } }),
586
+ /* @__PURE__ */ jsx4("span", { children: group.header })
587
+ ]
588
+ }
589
+ ),
590
+ !isCollapsed && group.steps.map((step) => /* @__PURE__ */ jsx4(
591
+ "div",
592
+ {
593
+ style: {
594
+ fontSize: fs.small,
595
+ lineHeight: 1.6,
596
+ color: isLatest ? theme.textSecondary : theme.textMuted,
597
+ padding: `2px ${pad - 4}px 2px ${pad + 20}px`,
598
+ opacity: isLatest ? 0.9 : 0.7,
599
+ transition: "all 0.15s ease"
600
+ },
601
+ "data-fp": "narrative-step",
602
+ children: step.text
603
+ },
604
+ step.idx
605
+ ))
606
+ ]
607
+ },
608
+ group.headerIdx
609
+ );
610
+ }),
611
+ futureGroups.length > 0 && /* @__PURE__ */ jsx4("div", { style: { opacity: 0.2 }, children: futureGroups.map((group) => /* @__PURE__ */ jsxs3("div", { style: { marginBottom: 2 }, children: [
612
+ /* @__PURE__ */ jsx4(
613
+ "div",
614
+ {
615
+ style: {
616
+ fontSize: fs.body,
617
+ lineHeight: 1.7,
618
+ color: theme.textMuted,
619
+ padding: `4px ${pad - 4}px`,
620
+ borderLeft: `3px solid ${theme.border}`,
621
+ fontWeight: 600,
622
+ paddingLeft: pad + 12
623
+ },
624
+ children: group.header
625
+ }
626
+ ),
627
+ group.steps.map((step) => /* @__PURE__ */ jsx4(
628
+ "div",
629
+ {
630
+ style: {
631
+ fontSize: fs.small,
632
+ lineHeight: 1.6,
633
+ color: theme.textMuted,
634
+ padding: `2px ${pad - 4}px 2px ${pad + 20}px`
635
+ },
636
+ children: step.text
637
+ },
638
+ `f-${step.idx}`
639
+ ))
640
+ ] }, `f-${group.headerIdx}`)) })
641
+ ]
642
+ }
643
+ );
644
+ }
645
+
646
+ // src/components/GanttTimeline/GanttTimeline.tsx
647
+ import { useMemo as useMemo4 } from "react";
648
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
649
+ function GanttTimeline({
650
+ snapshots,
651
+ selectedIndex = 0,
652
+ onSelect,
653
+ size = "default",
654
+ unstyled = false,
655
+ className,
656
+ style
657
+ }) {
658
+ const totalWallTime = useMemo4(
659
+ () => Math.max(...snapshots.map((s) => s.startMs + s.durationMs), 1),
660
+ [snapshots]
661
+ );
662
+ const fs = fontSize[size];
663
+ const pad = padding[size];
664
+ const labelWidth = size === "compact" ? 50 : size === "detailed" ? 100 : 80;
665
+ const msWidth = size === "compact" ? 28 : 36;
666
+ if (unstyled) {
667
+ return /* @__PURE__ */ jsx5("div", { className, style, "data-fp": "gantt-timeline", children: snapshots.map((snap, idx) => /* @__PURE__ */ jsxs4(
668
+ "div",
669
+ {
670
+ "data-fp": "gantt-bar",
671
+ "data-selected": idx === selectedIndex,
672
+ "data-visible": idx <= selectedIndex,
673
+ onClick: () => onSelect?.(idx),
674
+ children: [
675
+ /* @__PURE__ */ jsx5("span", { "data-fp": "gantt-label", children: snap.stageLabel }),
676
+ /* @__PURE__ */ jsxs4("span", { "data-fp": "gantt-duration", children: [
677
+ snap.durationMs,
678
+ "ms"
679
+ ] })
680
+ ]
681
+ },
682
+ snap.stageName
683
+ )) });
684
+ }
685
+ return /* @__PURE__ */ jsxs4(
686
+ "div",
687
+ {
688
+ className,
689
+ style: { padding: pad, fontFamily: theme.fontSans, ...style },
690
+ "data-fp": "gantt-timeline",
691
+ children: [
692
+ /* @__PURE__ */ jsx5(
693
+ "span",
694
+ {
695
+ style: {
696
+ fontSize: fs.label,
697
+ fontWeight: 600,
698
+ color: theme.textMuted,
699
+ textTransform: "uppercase",
700
+ letterSpacing: "0.08em"
701
+ },
702
+ children: size === "compact" ? "Timeline" : "Execution Timeline"
703
+ }
704
+ ),
705
+ /* @__PURE__ */ jsx5(
706
+ "div",
707
+ {
708
+ style: {
709
+ marginTop: 8,
710
+ display: "flex",
711
+ flexDirection: "column",
712
+ gap: 4
713
+ },
714
+ children: snapshots.map((snap, idx) => {
715
+ const leftPct = snap.startMs / totalWallTime * 100;
716
+ const widthPct = Math.max(snap.durationMs / totalWallTime * 100, 1);
717
+ const isSelected = idx === selectedIndex;
718
+ const isVisible = idx <= selectedIndex;
719
+ return /* @__PURE__ */ jsxs4(
720
+ "div",
721
+ {
722
+ onClick: () => onSelect?.(idx),
723
+ style: {
724
+ display: "flex",
725
+ alignItems: "center",
726
+ gap: size === "compact" ? 4 : 8,
727
+ cursor: onSelect ? "pointer" : "default",
728
+ opacity: isVisible ? 1 : 0.3,
729
+ transition: "opacity 0.3s ease"
730
+ },
731
+ children: [
732
+ /* @__PURE__ */ jsx5(
733
+ "span",
734
+ {
735
+ style: {
736
+ width: labelWidth,
737
+ fontSize: fs.small,
738
+ color: isSelected ? theme.primary : theme.textMuted,
739
+ fontWeight: isSelected ? 600 : 400,
740
+ textAlign: "right",
741
+ flexShrink: 0,
742
+ overflow: "hidden",
743
+ textOverflow: "ellipsis",
744
+ whiteSpace: "nowrap"
745
+ },
746
+ children: snap.stageLabel
747
+ }
748
+ ),
749
+ /* @__PURE__ */ jsx5(
750
+ "div",
751
+ {
752
+ style: {
753
+ flex: 1,
754
+ height: size === "compact" ? 6 : 8,
755
+ position: "relative",
756
+ background: theme.bgTertiary,
757
+ borderRadius: 3
758
+ },
759
+ children: isVisible && /* @__PURE__ */ jsx5(
760
+ "div",
761
+ {
762
+ style: {
763
+ position: "absolute",
764
+ left: `${leftPct}%`,
765
+ top: 0,
766
+ width: `${widthPct}%`,
767
+ height: "100%",
768
+ borderRadius: 3,
769
+ background: isSelected ? theme.primary : theme.success,
770
+ transition: "width 0.3s ease"
771
+ }
772
+ }
773
+ )
774
+ }
775
+ ),
776
+ /* @__PURE__ */ jsxs4(
777
+ "span",
778
+ {
779
+ style: {
780
+ fontSize: fs.small,
781
+ color: theme.textMuted,
782
+ fontFamily: theme.fontMono,
783
+ width: msWidth,
784
+ flexShrink: 0
785
+ },
786
+ children: [
787
+ snap.durationMs,
788
+ "ms"
789
+ ]
790
+ }
791
+ )
792
+ ]
793
+ },
794
+ snap.stageName
795
+ );
796
+ })
797
+ }
798
+ ),
799
+ /* @__PURE__ */ jsxs4(
800
+ "div",
801
+ {
802
+ style: {
803
+ marginTop: 4,
804
+ marginLeft: labelWidth + (size === "compact" ? 4 : 8),
805
+ marginRight: msWidth + (size === "compact" ? 4 : 8),
806
+ display: "flex",
807
+ justifyContent: "space-between",
808
+ fontSize: fs.small - 1,
809
+ color: theme.textMuted,
810
+ fontFamily: theme.fontMono
811
+ },
812
+ children: [
813
+ /* @__PURE__ */ jsx5("span", { children: "0ms" }),
814
+ size !== "compact" && /* @__PURE__ */ jsxs4("span", { children: [
815
+ (totalWallTime / 2).toFixed(1),
816
+ "ms"
817
+ ] }),
818
+ /* @__PURE__ */ jsxs4("span", { children: [
819
+ totalWallTime.toFixed(1),
820
+ "ms"
821
+ ] })
822
+ ]
823
+ }
824
+ )
825
+ ]
826
+ }
827
+ );
828
+ }
829
+
830
+ // src/components/SnapshotPanel/SnapshotPanel.tsx
831
+ import { useState as useState2 } from "react";
832
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
833
+ function SnapshotPanel({
834
+ snapshots,
835
+ showGantt = true,
836
+ showScrubber = true,
837
+ title = "Pipeline Inspector",
838
+ size = "default",
839
+ unstyled = false,
840
+ className,
841
+ style
842
+ }) {
843
+ const [selectedIndex, setSelectedIndex] = useState2(0);
844
+ const fs = fontSize[size];
845
+ const pad = padding[size];
846
+ if (snapshots.length === 0) {
847
+ return /* @__PURE__ */ jsx6(
848
+ "div",
849
+ {
850
+ className,
851
+ style: {
852
+ padding: pad * 2,
853
+ textAlign: "center",
854
+ color: unstyled ? void 0 : theme.textMuted,
855
+ fontSize: fs.body,
856
+ ...style
857
+ },
858
+ "data-fp": "snapshot-panel",
859
+ children: "No snapshots to display"
860
+ }
861
+ );
862
+ }
863
+ if (unstyled) {
864
+ return /* @__PURE__ */ jsxs5("div", { className, style, "data-fp": "snapshot-panel", children: [
865
+ /* @__PURE__ */ jsx6("h3", { children: title }),
866
+ showScrubber && /* @__PURE__ */ jsx6(
867
+ "input",
868
+ {
869
+ type: "range",
870
+ min: 0,
871
+ max: snapshots.length - 1,
872
+ value: selectedIndex,
873
+ onChange: (e) => setSelectedIndex(parseInt(e.target.value))
874
+ }
875
+ ),
876
+ /* @__PURE__ */ jsx6(
877
+ MemoryInspector,
878
+ {
879
+ snapshots,
880
+ selectedIndex,
881
+ unstyled: true
882
+ }
883
+ ),
884
+ /* @__PURE__ */ jsx6(
885
+ NarrativeLog,
886
+ {
887
+ snapshots,
888
+ selectedIndex,
889
+ unstyled: true
890
+ }
891
+ ),
892
+ showGantt && /* @__PURE__ */ jsx6(
893
+ GanttTimeline,
894
+ {
895
+ snapshots,
896
+ selectedIndex,
897
+ onSelect: setSelectedIndex,
898
+ unstyled: true
899
+ }
900
+ )
901
+ ] });
902
+ }
903
+ return /* @__PURE__ */ jsxs5(
904
+ "div",
905
+ {
906
+ className,
907
+ style: {
908
+ display: "flex",
909
+ flexDirection: "column",
910
+ height: "100%",
911
+ background: theme.bgPrimary,
912
+ fontFamily: theme.fontSans,
913
+ overflow: "hidden",
914
+ ...style
915
+ },
916
+ "data-fp": "snapshot-panel",
917
+ children: [
918
+ /* @__PURE__ */ jsxs5(
919
+ "div",
920
+ {
921
+ style: {
922
+ padding: `${pad}px ${pad + 4}px`,
923
+ borderBottom: `1px solid ${theme.border}`,
924
+ background: theme.bgSecondary,
925
+ flexShrink: 0
926
+ },
927
+ children: [
928
+ /* @__PURE__ */ jsxs5(
929
+ "div",
930
+ {
931
+ style: {
932
+ display: "flex",
933
+ alignItems: "center",
934
+ gap: 8,
935
+ marginBottom: showScrubber ? 8 : 0
936
+ },
937
+ children: [
938
+ /* @__PURE__ */ jsx6(
939
+ "span",
940
+ {
941
+ style: {
942
+ fontSize: fs.body + 2,
943
+ fontWeight: 600,
944
+ color: theme.textPrimary
945
+ },
946
+ children: title
947
+ }
948
+ ),
949
+ /* @__PURE__ */ jsxs5(
950
+ "span",
951
+ {
952
+ style: {
953
+ fontSize: fs.small,
954
+ color: theme.textMuted,
955
+ fontFamily: theme.fontMono
956
+ },
957
+ children: [
958
+ selectedIndex + 1,
959
+ "/",
960
+ snapshots.length
961
+ ]
962
+ }
963
+ )
964
+ ]
965
+ }
966
+ ),
967
+ showScrubber && /* @__PURE__ */ jsxs5("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
968
+ /* @__PURE__ */ jsx6(
969
+ ScrubButton,
970
+ {
971
+ label: "\\u25C0",
972
+ disabled: selectedIndex === 0,
973
+ onClick: () => setSelectedIndex((i) => Math.max(0, i - 1))
974
+ }
975
+ ),
976
+ /* @__PURE__ */ jsx6(
977
+ "input",
978
+ {
979
+ type: "range",
980
+ min: 0,
981
+ max: snapshots.length - 1,
982
+ value: selectedIndex,
983
+ onChange: (e) => setSelectedIndex(parseInt(e.target.value)),
984
+ style: {
985
+ flex: 1,
986
+ height: 4,
987
+ accentColor: theme.primary,
988
+ cursor: "pointer"
989
+ }
990
+ }
991
+ ),
992
+ /* @__PURE__ */ jsx6(
993
+ ScrubButton,
994
+ {
995
+ label: "\\u25B6",
996
+ disabled: selectedIndex === snapshots.length - 1,
997
+ onClick: () => setSelectedIndex((i) => Math.min(snapshots.length - 1, i + 1))
998
+ }
999
+ )
1000
+ ] })
1001
+ ]
1002
+ }
1003
+ ),
1004
+ /* @__PURE__ */ jsxs5("div", { style: { flex: 1, overflow: "auto" }, children: [
1005
+ /* @__PURE__ */ jsx6(
1006
+ MemoryInspector,
1007
+ {
1008
+ snapshots,
1009
+ selectedIndex,
1010
+ size
1011
+ }
1012
+ ),
1013
+ /* @__PURE__ */ jsx6(
1014
+ "div",
1015
+ {
1016
+ style: {
1017
+ height: 1,
1018
+ background: theme.border,
1019
+ margin: `0 ${pad}px`
1020
+ }
1021
+ }
1022
+ ),
1023
+ /* @__PURE__ */ jsx6(
1024
+ NarrativeLog,
1025
+ {
1026
+ snapshots,
1027
+ selectedIndex,
1028
+ size
1029
+ }
1030
+ )
1031
+ ] }),
1032
+ showGantt && /* @__PURE__ */ jsx6(
1033
+ "div",
1034
+ {
1035
+ style: {
1036
+ borderTop: `1px solid ${theme.border}`,
1037
+ background: theme.bgSecondary,
1038
+ flexShrink: 0
1039
+ },
1040
+ children: /* @__PURE__ */ jsx6(
1041
+ GanttTimeline,
1042
+ {
1043
+ snapshots,
1044
+ selectedIndex,
1045
+ onSelect: setSelectedIndex,
1046
+ size
1047
+ }
1048
+ )
1049
+ }
1050
+ )
1051
+ ]
1052
+ }
1053
+ );
1054
+ }
1055
+ function ScrubButton({
1056
+ label,
1057
+ disabled,
1058
+ onClick
1059
+ }) {
1060
+ return /* @__PURE__ */ jsx6(
1061
+ "button",
1062
+ {
1063
+ onClick,
1064
+ disabled,
1065
+ style: {
1066
+ background: theme.bgTertiary,
1067
+ border: `1px solid ${theme.border}`,
1068
+ color: disabled ? theme.textMuted : theme.textPrimary,
1069
+ borderRadius: 6,
1070
+ width: 28,
1071
+ height: 28,
1072
+ display: "flex",
1073
+ alignItems: "center",
1074
+ justifyContent: "center",
1075
+ cursor: disabled ? "not-allowed" : "pointer",
1076
+ opacity: disabled ? 0.5 : 1,
1077
+ fontSize: 12,
1078
+ flexShrink: 0
1079
+ },
1080
+ children: label
1081
+ }
1082
+ );
1083
+ }
1084
+
1085
+ // src/components/ScopeDiff/ScopeDiff.tsx
1086
+ import { useMemo as useMemo5 } from "react";
1087
+ import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1088
+ function computeDiff(prev, curr) {
1089
+ const entries = [];
1090
+ const allKeys = /* @__PURE__ */ new Set([...Object.keys(prev ?? {}), ...Object.keys(curr)]);
1091
+ for (const key of allKeys) {
1092
+ const inPrev = prev != null && key in prev;
1093
+ const inCurr = key in curr;
1094
+ const oldVal = prev?.[key];
1095
+ const newVal = curr[key];
1096
+ if (!inPrev && inCurr) {
1097
+ entries.push({ key, type: "added", newValue: newVal });
1098
+ } else if (inPrev && !inCurr) {
1099
+ entries.push({ key, type: "removed", oldValue: oldVal });
1100
+ } else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
1101
+ entries.push({ key, type: "changed", oldValue: oldVal, newValue: newVal });
1102
+ } else {
1103
+ entries.push({ key, type: "unchanged", newValue: newVal });
1104
+ }
1105
+ }
1106
+ const order = { added: 0, changed: 1, removed: 2, unchanged: 3 };
1107
+ entries.sort((a, b) => order[a.type] - order[b.type]);
1108
+ return entries;
1109
+ }
1110
+ function fmt(v2) {
1111
+ if (typeof v2 === "string") return `"${v2}"`;
1112
+ if (typeof v2 === "object" && v2 !== null) return JSON.stringify(v2, null, 2);
1113
+ return String(v2);
1114
+ }
1115
+ var diffColors = {
1116
+ added: { bg: "rgba(34,197,94,0.10)", fg: "#22c55e", icon: "+" },
1117
+ removed: { bg: "rgba(239,68,68,0.10)", fg: "#ef4444", icon: "-" },
1118
+ changed: { bg: "rgba(245,158,11,0.10)", fg: "#f59e0b", icon: "~" },
1119
+ unchanged: { bg: "transparent", fg: "", icon: " " }
1120
+ };
1121
+ function ScopeDiff({
1122
+ previous,
1123
+ current,
1124
+ hideUnchanged = false,
1125
+ size = "default",
1126
+ unstyled = false,
1127
+ className,
1128
+ style
1129
+ }) {
1130
+ const entries = useMemo5(() => computeDiff(previous, current), [previous, current]);
1131
+ const visible = hideUnchanged ? entries.filter((e) => e.type !== "unchanged") : entries;
1132
+ const fs = fontSize[size];
1133
+ const pad = padding[size];
1134
+ if (unstyled) {
1135
+ return /* @__PURE__ */ jsx7("div", { className, style, "data-fp": "scope-diff", children: visible.map((e) => /* @__PURE__ */ jsxs6("div", { "data-fp": "diff-entry", "data-type": e.type, children: [
1136
+ /* @__PURE__ */ jsx7("span", { "data-fp": "diff-key", children: e.key }),
1137
+ e.type === "changed" && /* @__PURE__ */ jsxs6(Fragment, { children: [
1138
+ /* @__PURE__ */ jsx7("span", { "data-fp": "diff-old", children: fmt(e.oldValue) }),
1139
+ /* @__PURE__ */ jsx7("span", { "data-fp": "diff-new", children: fmt(e.newValue) })
1140
+ ] }),
1141
+ (e.type === "added" || e.type === "unchanged") && /* @__PURE__ */ jsx7("span", { "data-fp": "diff-value", children: fmt(e.newValue) }),
1142
+ e.type === "removed" && /* @__PURE__ */ jsx7("span", { "data-fp": "diff-value", children: fmt(e.oldValue) })
1143
+ ] }, e.key)) });
1144
+ }
1145
+ return /* @__PURE__ */ jsxs6(
1146
+ "div",
1147
+ {
1148
+ className,
1149
+ style: { padding: pad, fontFamily: theme.fontMono, ...style },
1150
+ "data-fp": "scope-diff",
1151
+ children: [
1152
+ visible.length === 0 && /* @__PURE__ */ jsx7("div", { style: { fontSize: fs.body, color: theme.textMuted, fontStyle: "italic" }, children: "No changes" }),
1153
+ visible.map((entry) => {
1154
+ const dc = diffColors[entry.type];
1155
+ return /* @__PURE__ */ jsxs6(
1156
+ "div",
1157
+ {
1158
+ style: {
1159
+ display: "flex",
1160
+ alignItems: "flex-start",
1161
+ gap: 8,
1162
+ padding: `4px ${pad - 4}px`,
1163
+ marginBottom: 2,
1164
+ borderRadius: 4,
1165
+ background: dc.bg,
1166
+ fontSize: fs.body,
1167
+ lineHeight: 1.5
1168
+ },
1169
+ "data-fp": "diff-entry",
1170
+ children: [
1171
+ /* @__PURE__ */ jsx7(
1172
+ "span",
1173
+ {
1174
+ style: {
1175
+ width: 16,
1176
+ flexShrink: 0,
1177
+ fontWeight: 700,
1178
+ color: dc.fg || theme.textMuted,
1179
+ textAlign: "center"
1180
+ },
1181
+ children: dc.icon
1182
+ }
1183
+ ),
1184
+ /* @__PURE__ */ jsx7("span", { style: { color: theme.primary, fontWeight: 600, flexShrink: 0 }, children: entry.key }),
1185
+ /* @__PURE__ */ jsx7("span", { style: { color: theme.textMuted }, children: "=" }),
1186
+ entry.type === "changed" ? /* @__PURE__ */ jsxs6("span", { children: [
1187
+ /* @__PURE__ */ jsx7(
1188
+ "span",
1189
+ {
1190
+ style: {
1191
+ color: theme.error,
1192
+ textDecoration: "line-through",
1193
+ opacity: 0.7
1194
+ },
1195
+ children: fmt(entry.oldValue)
1196
+ }
1197
+ ),
1198
+ /* @__PURE__ */ jsx7("span", { style: { color: theme.textMuted, margin: "0 4px" }, children: "\u2192" }),
1199
+ /* @__PURE__ */ jsx7("span", { style: { color: theme.success }, children: fmt(entry.newValue) })
1200
+ ] }) : /* @__PURE__ */ jsx7(
1201
+ "span",
1202
+ {
1203
+ style: {
1204
+ color: entry.type === "added" ? theme.success : entry.type === "removed" ? theme.error : theme.textPrimary
1205
+ },
1206
+ children: fmt(entry.type === "removed" ? entry.oldValue : entry.newValue)
1207
+ }
1208
+ )
1209
+ ]
1210
+ },
1211
+ entry.key
1212
+ );
1213
+ })
1214
+ ]
1215
+ }
1216
+ );
1217
+ }
1218
+
1219
+ // src/components/ResultPanel/ResultPanel.tsx
1220
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1221
+ function ResultPanel({
1222
+ data,
1223
+ logs = [],
1224
+ hideConsole = false,
1225
+ size = "default",
1226
+ unstyled = false,
1227
+ className,
1228
+ style
1229
+ }) {
1230
+ const fs = fontSize[size];
1231
+ const pad = padding[size];
1232
+ if (unstyled) {
1233
+ return /* @__PURE__ */ jsxs7("div", { className, style, "data-fp": "result-panel", children: [
1234
+ /* @__PURE__ */ jsx8("div", { "data-fp": "result-data", children: /* @__PURE__ */ jsx8("pre", { children: data ? JSON.stringify(data, null, 2) : "No data" }) }),
1235
+ !hideConsole && /* @__PURE__ */ jsx8("div", { "data-fp": "result-console", children: logs.map((line, i) => /* @__PURE__ */ jsx8("div", { "data-fp": "console-line", "data-error": line.startsWith("ERROR"), children: line }, i)) })
1236
+ ] });
1237
+ }
1238
+ return /* @__PURE__ */ jsxs7(
1239
+ "div",
1240
+ {
1241
+ className,
1242
+ style: {
1243
+ height: "100%",
1244
+ display: "flex",
1245
+ flexDirection: "column",
1246
+ overflow: "hidden",
1247
+ ...style
1248
+ },
1249
+ "data-fp": "result-panel",
1250
+ children: [
1251
+ data && /* @__PURE__ */ jsxs7("div", { style: { flex: 1, overflow: "auto", padding: pad }, children: [
1252
+ /* @__PURE__ */ jsx8(
1253
+ "div",
1254
+ {
1255
+ style: {
1256
+ fontSize: fs.label,
1257
+ fontWeight: 600,
1258
+ color: theme.textMuted,
1259
+ textTransform: "uppercase",
1260
+ letterSpacing: "0.08em",
1261
+ marginBottom: 8
1262
+ },
1263
+ children: size === "compact" ? "Result" : "Business Result (Scope)"
1264
+ }
1265
+ ),
1266
+ /* @__PURE__ */ jsx8(
1267
+ "pre",
1268
+ {
1269
+ style: {
1270
+ fontSize: fs.body,
1271
+ fontFamily: theme.fontMono,
1272
+ color: theme.textPrimary,
1273
+ background: theme.bgSecondary,
1274
+ padding: pad,
1275
+ borderRadius: theme.radius,
1276
+ overflow: "auto",
1277
+ margin: 0
1278
+ },
1279
+ children: JSON.stringify(data, null, 2)
1280
+ }
1281
+ )
1282
+ ] }),
1283
+ !hideConsole && /* @__PURE__ */ jsxs7(
1284
+ "div",
1285
+ {
1286
+ style: {
1287
+ borderTop: `1px solid ${theme.border}`,
1288
+ padding: pad,
1289
+ overflow: "auto",
1290
+ maxHeight: "40%",
1291
+ flexShrink: 0
1292
+ },
1293
+ children: [
1294
+ /* @__PURE__ */ jsx8(
1295
+ "div",
1296
+ {
1297
+ style: {
1298
+ fontSize: fs.label,
1299
+ fontWeight: 600,
1300
+ color: theme.textMuted,
1301
+ textTransform: "uppercase",
1302
+ letterSpacing: "0.08em",
1303
+ marginBottom: 8
1304
+ },
1305
+ children: "Console"
1306
+ }
1307
+ ),
1308
+ logs.length === 0 && /* @__PURE__ */ jsx8("div", { style: { fontSize: fs.body, color: theme.textMuted, fontStyle: "italic" }, children: "No console output" }),
1309
+ logs.map((line, i) => /* @__PURE__ */ jsx8(
1310
+ "div",
1311
+ {
1312
+ style: {
1313
+ fontSize: fs.body,
1314
+ fontFamily: theme.fontMono,
1315
+ color: line.startsWith("ERROR") ? theme.error : theme.textPrimary,
1316
+ padding: "2px 0",
1317
+ borderBottom: `1px solid ${theme.bgSecondary}`,
1318
+ whiteSpace: "pre-wrap",
1319
+ wordBreak: "break-word"
1320
+ },
1321
+ children: line
1322
+ },
1323
+ i
1324
+ ))
1325
+ ]
1326
+ }
1327
+ )
1328
+ ]
1329
+ }
1330
+ );
1331
+ }
1332
+
1333
+ // src/components/TimeTravelControls/TimeTravelControls.tsx
1334
+ import { useState as useState3, useEffect as useEffect2, useRef as useRef2, useCallback as useCallback2 } from "react";
1335
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1336
+ function TimeTravelControls({
1337
+ snapshots,
1338
+ selectedIndex,
1339
+ onIndexChange,
1340
+ autoPlayable = true,
1341
+ size = "default",
1342
+ unstyled = false,
1343
+ className,
1344
+ style
1345
+ }) {
1346
+ const [playing, setPlaying] = useState3(false);
1347
+ const playRef = useRef2(null);
1348
+ const total = snapshots.length;
1349
+ const canPrev = selectedIndex > 0;
1350
+ const canNext = selectedIndex < total - 1;
1351
+ useEffect2(() => {
1352
+ if (!playing || !autoPlayable) return;
1353
+ if (selectedIndex >= total - 1) {
1354
+ setPlaying(false);
1355
+ return;
1356
+ }
1357
+ const stageDur = snapshots[selectedIndex]?.durationMs ?? 1;
1358
+ const totalDur = snapshots.reduce((s, snap) => s + snap.durationMs, 0) || 1;
1359
+ const fraction = stageDur / totalDur;
1360
+ const baseMs = 3e3;
1361
+ const delay = Math.max(200, Math.min(fraction * baseMs, 2e3));
1362
+ playRef.current = setTimeout(() => {
1363
+ onIndexChange(selectedIndex + 1);
1364
+ }, delay);
1365
+ return () => {
1366
+ if (playRef.current) clearTimeout(playRef.current);
1367
+ };
1368
+ }, [playing, selectedIndex, snapshots, total, onIndexChange, autoPlayable]);
1369
+ const togglePlay = useCallback2(() => {
1370
+ if (playing) {
1371
+ setPlaying(false);
1372
+ } else {
1373
+ if (selectedIndex >= total - 1) onIndexChange(0);
1374
+ setPlaying(true);
1375
+ }
1376
+ }, [playing, selectedIndex, total, onIndexChange]);
1377
+ const fs = fontSize[size];
1378
+ if (unstyled) {
1379
+ return /* @__PURE__ */ jsxs8("div", { className, style, "data-fp": "time-travel-controls", children: [
1380
+ /* @__PURE__ */ jsx9(
1381
+ "button",
1382
+ {
1383
+ "data-fp": "tt-prev",
1384
+ disabled: !canPrev || playing,
1385
+ onClick: () => {
1386
+ setPlaying(false);
1387
+ onIndexChange(selectedIndex - 1);
1388
+ },
1389
+ children: "Prev"
1390
+ }
1391
+ ),
1392
+ autoPlayable && /* @__PURE__ */ jsx9("button", { "data-fp": "tt-play", onClick: togglePlay, children: playing ? "Pause" : "Play" }),
1393
+ /* @__PURE__ */ jsx9(
1394
+ "button",
1395
+ {
1396
+ "data-fp": "tt-next",
1397
+ disabled: !canNext || playing,
1398
+ onClick: () => {
1399
+ setPlaying(false);
1400
+ onIndexChange(selectedIndex + 1);
1401
+ },
1402
+ children: "Next"
1403
+ }
1404
+ ),
1405
+ /* @__PURE__ */ jsx9("div", { "data-fp": "tt-ticks", children: snapshots.map((snap, i) => /* @__PURE__ */ jsx9(
1406
+ "button",
1407
+ {
1408
+ "data-fp": "tt-tick",
1409
+ "data-active": i === selectedIndex,
1410
+ "data-done": i < selectedIndex,
1411
+ onClick: () => {
1412
+ setPlaying(false);
1413
+ onIndexChange(i);
1414
+ },
1415
+ title: snap.stageLabel
1416
+ },
1417
+ i
1418
+ )) })
1419
+ ] });
1420
+ }
1421
+ const btnStyle = (disabled) => ({
1422
+ background: theme.bgTertiary,
1423
+ border: `1px solid ${theme.border}`,
1424
+ color: disabled ? theme.textMuted : theme.textPrimary,
1425
+ borderRadius: "6px",
1426
+ padding: "4px 12px",
1427
+ fontSize: fs.body,
1428
+ fontWeight: 600,
1429
+ cursor: disabled ? "not-allowed" : "pointer",
1430
+ opacity: disabled ? 0.5 : 1,
1431
+ flexShrink: 0
1432
+ });
1433
+ return /* @__PURE__ */ jsxs8(
1434
+ "div",
1435
+ {
1436
+ className,
1437
+ style: {
1438
+ padding: "6px 12px",
1439
+ background: theme.bgSecondary,
1440
+ borderBottom: `1px solid ${theme.border}`,
1441
+ display: "flex",
1442
+ alignItems: "center",
1443
+ gap: 6,
1444
+ flexShrink: 0,
1445
+ ...style
1446
+ },
1447
+ "data-fp": "time-travel-controls",
1448
+ children: [
1449
+ /* @__PURE__ */ jsx9(
1450
+ "button",
1451
+ {
1452
+ style: btnStyle(!canPrev || playing),
1453
+ disabled: !canPrev || playing,
1454
+ onClick: () => {
1455
+ setPlaying(false);
1456
+ onIndexChange(selectedIndex - 1);
1457
+ },
1458
+ children: "\u25C0"
1459
+ }
1460
+ ),
1461
+ autoPlayable && /* @__PURE__ */ jsx9(
1462
+ "button",
1463
+ {
1464
+ onClick: togglePlay,
1465
+ style: {
1466
+ background: playing ? theme.primary : theme.bgTertiary,
1467
+ border: `1px solid ${theme.border}`,
1468
+ color: playing ? "white" : theme.textPrimary,
1469
+ borderRadius: "6px",
1470
+ width: 28,
1471
+ height: 28,
1472
+ display: "flex",
1473
+ alignItems: "center",
1474
+ justifyContent: "center",
1475
+ cursor: "pointer",
1476
+ fontSize: 14,
1477
+ flexShrink: 0
1478
+ },
1479
+ title: playing ? "Pause" : "Play",
1480
+ children: playing ? "\u23F8" : "\u25B6"
1481
+ }
1482
+ ),
1483
+ /* @__PURE__ */ jsx9(
1484
+ "button",
1485
+ {
1486
+ style: btnStyle(!canNext || playing),
1487
+ disabled: !canNext || playing,
1488
+ onClick: () => {
1489
+ setPlaying(false);
1490
+ onIndexChange(selectedIndex + 1);
1491
+ },
1492
+ children: "\u25B6"
1493
+ }
1494
+ ),
1495
+ /* @__PURE__ */ jsx9(
1496
+ "div",
1497
+ {
1498
+ style: {
1499
+ flex: 1,
1500
+ display: "flex",
1501
+ alignItems: "center",
1502
+ gap: 2,
1503
+ padding: "0 4px"
1504
+ },
1505
+ children: snapshots.map((snap, i) => {
1506
+ const isActive = i === selectedIndex;
1507
+ const isDone = i < selectedIndex;
1508
+ return /* @__PURE__ */ jsx9(
1509
+ "button",
1510
+ {
1511
+ onClick: () => {
1512
+ setPlaying(false);
1513
+ onIndexChange(i);
1514
+ },
1515
+ title: snap.stageLabel,
1516
+ style: {
1517
+ flex: 1,
1518
+ height: isActive ? 14 : 8,
1519
+ borderRadius: 3,
1520
+ border: "none",
1521
+ cursor: "pointer",
1522
+ background: isActive ? theme.primary : isDone ? theme.success : theme.bgTertiary,
1523
+ opacity: isDone || isActive ? 1 : 0.4,
1524
+ transition: "all 0.15s ease"
1525
+ }
1526
+ },
1527
+ i
1528
+ );
1529
+ })
1530
+ }
1531
+ )
1532
+ ]
1533
+ }
1534
+ );
1535
+ }
1536
+
1537
+ // src/components/ExplainableShell/ExplainableShell.tsx
1538
+ import { useState as useState4, useCallback as useCallback3, useMemo as useMemo6 } from "react";
1539
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1540
+ function ExplainableShell({
1541
+ snapshots,
1542
+ resultData,
1543
+ logs = [],
1544
+ narrative = [],
1545
+ tabs = ["result", "explainable", "ai-compatible"],
1546
+ defaultTab,
1547
+ hideConsole = false,
1548
+ renderFlowchart,
1549
+ size = "default",
1550
+ unstyled = false,
1551
+ className,
1552
+ style
1553
+ }) {
1554
+ const [activeTab, setActiveTab] = useState4(defaultTab ?? tabs[0]);
1555
+ const [snapshotIdx, setSnapshotIdx] = useState4(0);
1556
+ const fs = fontSize[size];
1557
+ const pad = padding[size];
1558
+ const handleSnapshotChange = useCallback3((idx) => {
1559
+ setSnapshotIdx(Math.max(0, Math.min(idx, snapshots.length - 1)));
1560
+ }, [snapshots.length]);
1561
+ const revealedCount = useMemo6(() => {
1562
+ if (snapshots.length === 0 || narrative.length === 0) return narrative.length;
1563
+ const boundaries = [];
1564
+ for (let i = 0; i < narrative.length; i++) {
1565
+ const trimmed = narrative[i].trimStart();
1566
+ if (trimmed.startsWith("Stage ") && !trimmed.match(/^Stage\s+\d+:\s*Step\s/) || trimmed.startsWith("[")) {
1567
+ boundaries.push(i);
1568
+ }
1569
+ }
1570
+ if (boundaries.length === 0) {
1571
+ const ratio = (snapshotIdx + 1) / snapshots.length;
1572
+ return Math.max(1, Math.ceil(narrative.length * ratio));
1573
+ }
1574
+ const groupsToShow = Math.max(
1575
+ 1,
1576
+ Math.min(
1577
+ Math.floor((snapshotIdx + 1) / snapshots.length * boundaries.length) || 1,
1578
+ boundaries.length
1579
+ )
1580
+ );
1581
+ const endIdx = groupsToShow < boundaries.length ? boundaries[groupsToShow] : narrative.length;
1582
+ return Math.max(1, endIdx);
1583
+ }, [snapshots.length, snapshotIdx, narrative]);
1584
+ const prevMemory = snapshotIdx > 0 ? snapshots[snapshotIdx - 1]?.memory : null;
1585
+ const currMemory = snapshots[snapshotIdx]?.memory ?? {};
1586
+ const tabLabels = {
1587
+ result: "Result",
1588
+ explainable: "Explainable",
1589
+ "ai-compatible": "AI-Compatible"
1590
+ };
1591
+ if (unstyled) {
1592
+ return /* @__PURE__ */ jsxs9("div", { className, style, "data-fp": "explainable-shell", children: [
1593
+ /* @__PURE__ */ jsx10("div", { "data-fp": "shell-tabs", children: tabs.map((tab) => /* @__PURE__ */ jsx10(
1594
+ "button",
1595
+ {
1596
+ "data-fp": "shell-tab",
1597
+ "data-active": tab === activeTab,
1598
+ onClick: () => setActiveTab(tab),
1599
+ children: tabLabels[tab]
1600
+ },
1601
+ tab
1602
+ )) }),
1603
+ /* @__PURE__ */ jsxs9("div", { "data-fp": "shell-content", "data-tab": activeTab, children: [
1604
+ activeTab === "result" && /* @__PURE__ */ jsx10(
1605
+ ResultPanel,
1606
+ {
1607
+ data: resultData ?? null,
1608
+ logs,
1609
+ hideConsole,
1610
+ unstyled: true
1611
+ }
1612
+ ),
1613
+ activeTab === "explainable" && /* @__PURE__ */ jsxs9(Fragment2, { children: [
1614
+ /* @__PURE__ */ jsx10(
1615
+ TimeTravelControls,
1616
+ {
1617
+ snapshots,
1618
+ selectedIndex: snapshotIdx,
1619
+ onIndexChange: handleSnapshotChange,
1620
+ unstyled: true
1621
+ }
1622
+ ),
1623
+ renderFlowchart?.({ snapshots, selectedIndex: snapshotIdx, onNodeClick: handleSnapshotChange }),
1624
+ /* @__PURE__ */ jsx10(MemoryInspector, { snapshots, selectedIndex: snapshotIdx, unstyled: true }),
1625
+ /* @__PURE__ */ jsx10(ScopeDiff, { previous: prevMemory, current: currMemory, unstyled: true }),
1626
+ /* @__PURE__ */ jsx10(
1627
+ GanttTimeline,
1628
+ {
1629
+ snapshots,
1630
+ selectedIndex: snapshotIdx,
1631
+ onSelect: handleSnapshotChange,
1632
+ unstyled: true
1633
+ }
1634
+ )
1635
+ ] }),
1636
+ activeTab === "ai-compatible" && /* @__PURE__ */ jsxs9(Fragment2, { children: [
1637
+ /* @__PURE__ */ jsx10(
1638
+ TimeTravelControls,
1639
+ {
1640
+ snapshots,
1641
+ selectedIndex: snapshotIdx,
1642
+ onIndexChange: handleSnapshotChange,
1643
+ unstyled: true
1644
+ }
1645
+ ),
1646
+ renderFlowchart?.({ snapshots, selectedIndex: snapshotIdx, onNodeClick: handleSnapshotChange }),
1647
+ /* @__PURE__ */ jsx10(
1648
+ NarrativeTrace,
1649
+ {
1650
+ narrative,
1651
+ revealedCount,
1652
+ unstyled: true
1653
+ }
1654
+ )
1655
+ ] })
1656
+ ] })
1657
+ ] });
1658
+ }
1659
+ return /* @__PURE__ */ jsxs9(
1660
+ "div",
1661
+ {
1662
+ className,
1663
+ style: {
1664
+ height: "100%",
1665
+ display: "flex",
1666
+ flexDirection: "column",
1667
+ overflow: "hidden",
1668
+ background: theme.bgPrimary,
1669
+ color: theme.textPrimary,
1670
+ fontFamily: theme.fontSans,
1671
+ ...style
1672
+ },
1673
+ "data-fp": "explainable-shell",
1674
+ children: [
1675
+ /* @__PURE__ */ jsx10(
1676
+ "div",
1677
+ {
1678
+ style: {
1679
+ display: "flex",
1680
+ gap: 0,
1681
+ borderBottom: `1px solid ${theme.border}`,
1682
+ background: theme.bgSecondary,
1683
+ flexShrink: 0
1684
+ },
1685
+ children: tabs.map((tab) => {
1686
+ const active = tab === activeTab;
1687
+ return /* @__PURE__ */ jsx10(
1688
+ "button",
1689
+ {
1690
+ onClick: () => setActiveTab(tab),
1691
+ style: {
1692
+ padding: `${pad - 4}px ${pad}px`,
1693
+ fontSize: fs.label,
1694
+ fontWeight: active ? 700 : 500,
1695
+ textTransform: "uppercase",
1696
+ letterSpacing: "0.08em",
1697
+ color: active ? theme.primary : theme.textMuted,
1698
+ background: "transparent",
1699
+ border: "none",
1700
+ borderBottom: active ? `2px solid ${theme.primary}` : "2px solid transparent",
1701
+ cursor: "pointer",
1702
+ transition: "all 0.15s ease"
1703
+ },
1704
+ children: tabLabels[tab]
1705
+ },
1706
+ tab
1707
+ );
1708
+ })
1709
+ }
1710
+ ),
1711
+ /* @__PURE__ */ jsxs9("div", { style: { flex: 1, overflow: "hidden", display: "flex", flexDirection: "column" }, children: [
1712
+ activeTab === "result" && /* @__PURE__ */ jsx10(
1713
+ ResultPanel,
1714
+ {
1715
+ data: resultData ?? null,
1716
+ logs,
1717
+ hideConsole,
1718
+ size
1719
+ }
1720
+ ),
1721
+ activeTab === "explainable" && /* @__PURE__ */ jsxs9(Fragment2, { children: [
1722
+ /* @__PURE__ */ jsx10(
1723
+ TimeTravelControls,
1724
+ {
1725
+ snapshots,
1726
+ selectedIndex: snapshotIdx,
1727
+ onIndexChange: handleSnapshotChange,
1728
+ size
1729
+ }
1730
+ ),
1731
+ /* @__PURE__ */ jsxs9("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
1732
+ renderFlowchart && /* @__PURE__ */ jsx10("div", { style: { flex: 1, overflow: "hidden", borderRight: `1px solid ${theme.border}` }, children: renderFlowchart({ snapshots, selectedIndex: snapshotIdx, onNodeClick: handleSnapshotChange }) }),
1733
+ /* @__PURE__ */ jsxs9(
1734
+ "div",
1735
+ {
1736
+ style: {
1737
+ width: renderFlowchart ? "40%" : "100%",
1738
+ minWidth: 280,
1739
+ overflow: "auto",
1740
+ display: "flex",
1741
+ flexDirection: "column"
1742
+ },
1743
+ children: [
1744
+ /* @__PURE__ */ jsx10(
1745
+ MemoryInspector,
1746
+ {
1747
+ snapshots,
1748
+ selectedIndex: snapshotIdx,
1749
+ size
1750
+ }
1751
+ ),
1752
+ /* @__PURE__ */ jsx10("div", { style: { borderTop: `1px solid ${theme.border}` }, children: /* @__PURE__ */ jsx10(
1753
+ ScopeDiff,
1754
+ {
1755
+ previous: prevMemory,
1756
+ current: currMemory,
1757
+ hideUnchanged: true,
1758
+ size
1759
+ }
1760
+ ) })
1761
+ ]
1762
+ }
1763
+ )
1764
+ ] }),
1765
+ /* @__PURE__ */ jsx10("div", { style: { borderTop: `1px solid ${theme.border}`, flexShrink: 0 }, children: /* @__PURE__ */ jsx10(
1766
+ GanttTimeline,
1767
+ {
1768
+ snapshots,
1769
+ selectedIndex: snapshotIdx,
1770
+ onSelect: handleSnapshotChange,
1771
+ size
1772
+ }
1773
+ ) })
1774
+ ] }),
1775
+ activeTab === "ai-compatible" && /* @__PURE__ */ jsxs9(Fragment2, { children: [
1776
+ /* @__PURE__ */ jsx10(
1777
+ TimeTravelControls,
1778
+ {
1779
+ snapshots,
1780
+ selectedIndex: snapshotIdx,
1781
+ onIndexChange: handleSnapshotChange,
1782
+ size
1783
+ }
1784
+ ),
1785
+ /* @__PURE__ */ jsxs9("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
1786
+ renderFlowchart && /* @__PURE__ */ jsx10("div", { style: { flex: 1, overflow: "hidden", borderRight: `1px solid ${theme.border}` }, children: renderFlowchart({ snapshots, selectedIndex: snapshotIdx, onNodeClick: handleSnapshotChange }) }),
1787
+ /* @__PURE__ */ jsx10(
1788
+ NarrativeTrace,
1789
+ {
1790
+ narrative,
1791
+ revealedCount,
1792
+ size,
1793
+ style: {
1794
+ width: renderFlowchart ? "40%" : "100%",
1795
+ minWidth: 280
1796
+ }
1797
+ }
1798
+ )
1799
+ ] })
1800
+ ] })
1801
+ ] })
1802
+ ]
1803
+ }
1804
+ );
1805
+ }
1806
+
1807
+ // src/adapters/fromRuntimeSnapshot.ts
1808
+ function toVisualizationSnapshots(runtime) {
1809
+ const snapshots = [];
1810
+ flattenTree(runtime.executionTree, snapshots, runtime.sharedState);
1811
+ return snapshots;
1812
+ }
1813
+ function flattenTree(node, out, sharedState, accumulatedMs = 0) {
1814
+ const durationMs = typeof node.metrics?.durationMs === "number" ? node.metrics.durationMs : 1;
1815
+ const startMs = accumulatedMs;
1816
+ const narrative = buildNarrative(node);
1817
+ const memory = {};
1818
+ if (node.logs) {
1819
+ Object.assign(memory, node.logs);
1820
+ }
1821
+ out.push({
1822
+ stageName: node.id,
1823
+ stageLabel: node.name || node.id,
1824
+ memory,
1825
+ narrative,
1826
+ startMs,
1827
+ durationMs,
1828
+ status: "done"
1829
+ });
1830
+ let nextMs = startMs + durationMs;
1831
+ if (node.children && node.children.length > 0) {
1832
+ let maxChildEnd = nextMs;
1833
+ for (const child of node.children) {
1834
+ const childEnd = flattenTree(child, out, sharedState, nextMs);
1835
+ maxChildEnd = Math.max(maxChildEnd, childEnd);
1836
+ }
1837
+ nextMs = maxChildEnd;
1838
+ }
1839
+ if (node.next) {
1840
+ nextMs = flattenTree(node.next, out, sharedState, nextMs);
1841
+ }
1842
+ return nextMs;
1843
+ }
1844
+ function buildNarrative(node) {
1845
+ const parts = [];
1846
+ if (node.name) {
1847
+ parts.push(`Stage "${node.name}" executed.`);
1848
+ }
1849
+ if (node.logs && Object.keys(node.logs).length > 0) {
1850
+ const keys = Object.keys(node.logs);
1851
+ parts.push(`Wrote ${keys.length} key(s): ${keys.join(", ")}.`);
1852
+ }
1853
+ if (node.errors && Object.keys(node.errors).length > 0) {
1854
+ parts.push(`Errors: ${JSON.stringify(node.errors)}`);
1855
+ }
1856
+ if (node.isFork) {
1857
+ parts.push(
1858
+ `Forked into ${node.children?.length ?? 0} parallel branch(es).`
1859
+ );
1860
+ }
1861
+ return parts.join(" ") || `Stage ${node.id} completed.`;
1862
+ }
1863
+ function createSnapshots(stages) {
1864
+ let accMs = 0;
1865
+ return stages.map((s) => {
1866
+ const duration = s.durationMs ?? 1;
1867
+ const snap = {
1868
+ stageName: s.name,
1869
+ stageLabel: s.label ?? s.name,
1870
+ memory: s.memory ?? {},
1871
+ narrative: s.narrative ?? `${s.label ?? s.name} completed.`,
1872
+ startMs: accMs,
1873
+ durationMs: duration,
1874
+ status: "done"
1875
+ };
1876
+ accMs += duration;
1877
+ return snap;
1878
+ });
1879
+ }
1880
+ export {
1881
+ ExplainableShell,
1882
+ FootprintTheme,
1883
+ GanttTimeline,
1884
+ MemoryInspector,
1885
+ NarrativeLog,
1886
+ NarrativeTrace,
1887
+ ResultPanel,
1888
+ ScopeDiff,
1889
+ SnapshotPanel,
1890
+ TimeTravelControls,
1891
+ coolDark,
1892
+ createSnapshots,
1893
+ defaultTokens,
1894
+ themePresets,
1895
+ toVisualizationSnapshots,
1896
+ tokensToCSSVars,
1897
+ useFootprintTheme,
1898
+ warmDark,
1899
+ warmLight
1900
+ };
1901
+ //# sourceMappingURL=index.js.map