footprint-explainable-ui 0.15.0 → 0.16.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.cjs CHANGED
@@ -4014,26 +4014,56 @@ var DataTracePanel = (0, import_react20.memo)(function DataTracePanel2({
4014
4014
  fromStageName
4015
4015
  }) {
4016
4016
  if (frames.length === 0) {
4017
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { padding: 12, color: theme.textMuted, fontSize: 13 }, children: "Select a stage to see its data dependency chain." });
4017
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { padding: "14px 14px 12px", fontSize: 13, lineHeight: 1.55 }, children: [
4018
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4019
+ "div",
4020
+ {
4021
+ style: {
4022
+ fontSize: 11,
4023
+ color: theme.textMuted,
4024
+ textTransform: "uppercase",
4025
+ letterSpacing: "0.5px",
4026
+ fontWeight: 600,
4027
+ marginBottom: 6
4028
+ },
4029
+ children: "Backward causal chain"
4030
+ }
4031
+ ),
4032
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { color: theme.textSecondary, marginBottom: 10 }, children: "Trace any value back to the stage that created it \u2014 and everything upstream that influenced it." }),
4033
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { color: theme.textMuted, fontSize: 12 }, children: "Select a stage above to see its dependency chain." })
4034
+ ] });
4018
4035
  }
4019
4036
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { padding: "8px 0", fontSize: 13 }, children: [
4020
- fromStageName && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4021
- "div",
4022
- {
4023
- style: {
4024
- padding: "4px 12px 8px",
4025
- fontSize: 11,
4026
- color: theme.textMuted,
4027
- textTransform: "uppercase",
4028
- letterSpacing: "0.5px",
4029
- fontWeight: 600
4030
- },
4031
- children: [
4032
- "Data trace from ",
4033
- fromStageName
4034
- ]
4035
- }
4036
- ),
4037
+ fromStageName && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { padding: "4px 12px 8px" }, children: [
4038
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4039
+ "div",
4040
+ {
4041
+ style: {
4042
+ fontSize: 11,
4043
+ color: theme.textMuted,
4044
+ textTransform: "uppercase",
4045
+ letterSpacing: "0.5px",
4046
+ fontWeight: 600
4047
+ },
4048
+ children: [
4049
+ "Data trace from ",
4050
+ fromStageName
4051
+ ]
4052
+ }
4053
+ ),
4054
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4055
+ "div",
4056
+ {
4057
+ style: {
4058
+ fontSize: 11,
4059
+ color: theme.textMuted,
4060
+ fontStyle: "italic",
4061
+ marginTop: 3
4062
+ },
4063
+ children: "Every value here was derived from the stages below."
4064
+ }
4065
+ )
4066
+ ] }),
4037
4067
  frames.map((frame, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4038
4068
  DataTraceFrame,
4039
4069
  {
@@ -4842,6 +4872,79 @@ function buildDataTrace(commitLog, targetRuntimeStageId, maxDepth = 10) {
4842
4872
  }
4843
4873
  return frames;
4844
4874
  }
4875
+ var RightPanel = (0, import_react24.memo)(function RightPanel2({
4876
+ mode,
4877
+ onModeChange,
4878
+ snapshots,
4879
+ selectedIndex,
4880
+ runtimeSnapshot,
4881
+ activeTab,
4882
+ allTabs,
4883
+ activeNarrativeEntries,
4884
+ activeNarrative,
4885
+ recorderViews,
4886
+ autoRecorderViews,
4887
+ size,
4888
+ onNavigateToStage
4889
+ }) {
4890
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
4891
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: {
4892
+ display: "flex",
4893
+ borderBottom: `1px solid ${theme.border}`,
4894
+ flexShrink: 0,
4895
+ background: theme.bgSecondary
4896
+ }, children: ["insights", "what"].map((m) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4897
+ "button",
4898
+ {
4899
+ onClick: () => onModeChange(m),
4900
+ style: {
4901
+ flex: 1,
4902
+ padding: "7px 12px",
4903
+ fontSize: 11,
4904
+ fontWeight: mode === m ? 700 : 500,
4905
+ textTransform: "uppercase",
4906
+ letterSpacing: "0.06em",
4907
+ color: mode === m ? theme.primary : theme.textMuted,
4908
+ background: "transparent",
4909
+ border: "none",
4910
+ borderBottom: mode === m ? `2px solid ${theme.primary}` : "2px solid transparent",
4911
+ cursor: "pointer",
4912
+ fontFamily: "inherit"
4913
+ },
4914
+ children: m === "insights" ? "Insights" : "Inspector"
4915
+ },
4916
+ m
4917
+ )) }),
4918
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflow: "hidden" }, children: mode === "insights" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4919
+ InsightPanel,
4920
+ {
4921
+ mode: "tabs",
4922
+ expandedId: activeTab,
4923
+ insights: allTabs.filter((t) => t.id !== "result" && t.id !== "memory").map((tab) => ({
4924
+ id: tab.id,
4925
+ name: insightName(tab.name),
4926
+ render: () => {
4927
+ if (tab.id === "narrative") return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(NarrativePanel, { snapshots, selectedIndex, narrativeEntries: activeNarrativeEntries, narrative: activeNarrative, size, style: { height: "100%" } });
4928
+ const customView = recorderViews?.find((v2) => v2.id === tab.id);
4929
+ if (customView?.render) return customView.render({ snapshots, selectedIndex });
4930
+ const autoView = autoRecorderViews.find((v2) => v2.id === tab.id);
4931
+ if (autoView) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(KeyedRecorderView, { data: autoView.data, description: autoView.description, preferredOperation: autoView.preferredOperation, snapshots, selectedIndex });
4932
+ return null;
4933
+ }
4934
+ }))
4935
+ }
4936
+ ) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4937
+ InspectorPanel,
4938
+ {
4939
+ snapshots,
4940
+ selectedIndex,
4941
+ dataTraceFrames: runtimeSnapshot?.commitLog ? buildDataTrace(runtimeSnapshot.commitLog, snapshots[selectedIndex]?.runtimeStageId ?? "") : [],
4942
+ selectedStageId: snapshots[selectedIndex]?.runtimeStageId,
4943
+ onNavigateToStage
4944
+ }
4945
+ ) })
4946
+ ] });
4947
+ });
4845
4948
  function insightName(name) {
4846
4949
  const map = {
4847
4950
  "Narrative": "Story",
@@ -4951,6 +5054,7 @@ function ExplainableShell({
4951
5054
  const [snapshotIdx, setSnapshotIdx] = (0, import_react24.useState)(0);
4952
5055
  const [drillDownStack, setDrillDownStack] = (0, import_react24.useState)([]);
4953
5056
  const [rightExpanded, setRightExpanded] = (0, import_react24.useState)(defaultExpanded?.details ?? true);
5057
+ const [rightPanelMode, setRightPanelMode] = (0, import_react24.useState)("insights");
4954
5058
  const [leftExpanded, setLeftExpanded] = (0, import_react24.useState)(defaultExpanded?.topology ?? false);
4955
5059
  const [timelineExpanded, setTimelineExpanded] = (0, import_react24.useState)(defaultExpanded?.timeline ?? false);
4956
5060
  (0, import_react24.useEffect)(() => {
@@ -5205,56 +5309,48 @@ function ExplainableShell({
5205
5309
  timelineExpanded && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flexShrink: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, size }) })
5206
5310
  ] })
5207
5311
  ) : (
5208
- /* ── Desktop: responsive layout ── */
5312
+ /* ── Desktop: two-column Flowchart | Right Panel ── */
5209
5313
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
5210
5314
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
5211
- showTopology && !isMedium && (leftExpanded ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { width: 280, flexShrink: 0, display: "flex", flexDirection: "row", overflow: "hidden" }, children: [
5212
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflow: "hidden" }, children: effectiveRenderFlowchart({
5213
- spec: activeSpec,
5214
- snapshots: activeSnapshots,
5215
- selectedIndex: safeIdx,
5216
- onNodeClick: handleNodeClick
5217
- }) }),
5218
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VLinePill, { label: leftLabel, expanded: true, side: "left", onClick: () => toggleLeft(false) })
5219
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VLinePill, { label: leftLabel, expanded: false, side: "left", onClick: () => toggleLeft(true) })),
5220
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: {
5221
- width: isMedium ? "50%" : 300,
5222
- flexShrink: isMedium ? 1 : 0,
5223
- flex: isMedium ? 1 : void 0,
5224
- overflow: "hidden",
5225
- borderRight: `1px solid ${theme.border}`
5226
- }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5227
- InspectorPanel,
5315
+ showTreeSidebar && (leftExpanded ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { width: 180, flexShrink: 0, display: "flex", flexDirection: "row", overflow: "hidden" }, children: [
5316
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5317
+ SubflowTree,
5318
+ {
5319
+ spec,
5320
+ activeStage: rootOverlay.activeStage,
5321
+ doneStages: rootOverlay.doneStages,
5322
+ onNodeSelect: handleTreeNodeSelect
5323
+ }
5324
+ ) }),
5325
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VLinePill, { label: "Topology", expanded: true, side: "left", onClick: () => toggleLeft(false) })
5326
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VLinePill, { label: "Topology", expanded: false, side: "left", onClick: () => toggleLeft(true) })),
5327
+ showTopology ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflow: "hidden", minWidth: 0 }, children: effectiveRenderFlowchart({
5328
+ spec: activeSpec,
5329
+ snapshots: activeSnapshots,
5330
+ selectedIndex: safeIdx,
5331
+ onNodeClick: handleNodeClick
5332
+ }) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1 } }),
5333
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VLinePill, { label: "Details", expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
5334
+ rightExpanded && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { width: "42%", minWidth: 320, maxWidth: 550, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5335
+ RightPanel,
5228
5336
  {
5337
+ mode: rightPanelMode,
5338
+ onModeChange: setRightPanelMode,
5229
5339
  snapshots: activeSnapshots,
5230
5340
  selectedIndex: safeIdx,
5231
- dataTraceFrames: runtimeSnapshot?.commitLog ? buildDataTrace(runtimeSnapshot.commitLog, activeSnapshots[safeIdx]?.runtimeStageId ?? "") : [],
5232
- selectedStageId: activeSnapshots[safeIdx]?.runtimeStageId,
5341
+ runtimeSnapshot,
5342
+ activeTab,
5343
+ allTabs,
5344
+ activeNarrativeEntries,
5345
+ activeNarrative,
5346
+ recorderViews,
5347
+ autoRecorderViews,
5348
+ size,
5233
5349
  onNavigateToStage: (id) => {
5234
5350
  const idx = activeSnapshots.findIndex((s) => s.runtimeStageId === id);
5235
5351
  if (idx >= 0) setSnapshotIdx(idx);
5236
5352
  }
5237
5353
  }
5238
- ) }),
5239
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5240
- InsightPanel,
5241
- {
5242
- mode: !leftExpanded && !isMedium ? "grid" : "tabs",
5243
- expandedId: activeTab,
5244
- insights: allTabs.filter((t) => t.id !== "result").map((tab) => ({
5245
- id: tab.id,
5246
- name: insightName(tab.name),
5247
- render: () => {
5248
- if (tab.id === "memory") return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, size, style: { height: "100%" } });
5249
- if (tab.id === "narrative") return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, narrative: activeNarrative, size, style: { height: "100%" } });
5250
- const customView = recorderViews?.find((v2) => v2.id === tab.id);
5251
- if (customView?.render) return customView.render({ snapshots: activeSnapshots, selectedIndex: safeIdx });
5252
- const autoView = autoRecorderViews.find((v2) => v2.id === tab.id);
5253
- if (autoView) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(KeyedRecorderView, { data: autoView.data, description: autoView.description, preferredOperation: autoView.preferredOperation, snapshots: activeSnapshots, selectedIndex: safeIdx });
5254
- return null;
5255
- }
5256
- }))
5257
- }
5258
5354
  ) })
5259
5355
  ] }),
5260
5356
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(