footprint-explainable-ui 0.9.0 → 0.10.1

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
@@ -3970,7 +3970,14 @@ function ExplainableShell({
3970
3970
  ro.observe(el);
3971
3971
  return () => ro.disconnect();
3972
3972
  }, []);
3973
- const [activeTab, setActiveTab] = (0, import_react19.useState)(defaultTab ?? tabs[0]);
3973
+ const builtInViews = [
3974
+ { id: "result", name: "Result" },
3975
+ { id: "memory", name: "Memory" },
3976
+ { id: "narrative", name: "Narrative" }
3977
+ ];
3978
+ const customViewIds = (recorderViews ?? []).map((v2) => ({ id: v2.id, name: v2.name }));
3979
+ const allTabs = [...builtInViews, ...customViewIds];
3980
+ const [activeTab, setActiveTab] = (0, import_react19.useState)(defaultTab ?? "memory");
3974
3981
  const [snapshotIdx, setSnapshotIdx] = (0, import_react19.useState)(0);
3975
3982
  const [drillDownStack, setDrillDownStack] = (0, import_react19.useState)([]);
3976
3983
  const [rightExpanded, setRightExpanded] = (0, import_react19.useState)(defaultExpanded?.details ?? true);
@@ -4033,7 +4040,6 @@ function ExplainableShell({
4033
4040
  const handleTabChange = (0, import_react19.useCallback)((tab) => {
4034
4041
  setActiveTab(tab);
4035
4042
  setDrillDownStack([]);
4036
- setSnapshotIdx(999);
4037
4043
  }, []);
4038
4044
  const handleSnapshotChange = (0, import_react19.useCallback)((idx) => {
4039
4045
  if (typeof idx === "number") setSnapshotIdx(idx);
@@ -4091,14 +4097,10 @@ function ExplainableShell({
4091
4097
  },
4092
4098
  [spec, snapshots, narrativeEntries, snapshotIdx]
4093
4099
  );
4094
- const tabLabels = {
4095
- result: "Result",
4096
- explainable: "Explainable",
4097
- "ai-compatible": "AI-Compatible"
4098
- };
4100
+ const tabLabels = new Map(allTabs.map((t) => [t.id, t.name]));
4099
4101
  if (unstyled) {
4100
4102
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className, style, "data-fp": "explainable-shell", children: [
4101
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { "data-fp": "shell-tabs", children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { "data-fp": "shell-tab", "data-active": tab === activeTab, onClick: () => handleTabChange(tab), children: tabLabels[tab] }, tab)) }),
4103
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { "data-fp": "shell-tabs", children: allTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { "data-fp": "shell-tab", "data-active": tab.id === activeTab, onClick: () => handleTabChange(tab.id), children: tab.name }, tab.id)) }),
4102
4104
  /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { "data-fp": "shell-content", "data-tab": activeTab, children: [
4103
4105
  activeTab === "result" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ResultPanel, { data: resultData ?? null, logs, hideConsole, unstyled: true }),
4104
4106
  (activeTab === "explainable" || activeTab === "ai-compatible") && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
@@ -4112,7 +4114,18 @@ function ExplainableShell({
4112
4114
  ] })
4113
4115
  ] });
4114
4116
  }
4115
- const isVisualizationTab = activeTab === "explainable" || activeTab === "ai-compatible";
4117
+ const isVisualizationTab = activeTab !== "result";
4118
+ const activeRecorderRender = (0, import_react19.useMemo)(() => {
4119
+ if (activeTab === "result") return null;
4120
+ if (activeTab === "memory") {
4121
+ return ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(MemoryPanel, { snapshots: snaps, selectedIndex: idx, size, style: { height: "100%" } });
4122
+ }
4123
+ if (activeTab === "narrative") {
4124
+ return ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(NarrativePanel, { snapshots: snaps, selectedIndex: idx, narrativeEntries: activeNarrativeEntries, narrative: activeNarrative, size, style: { height: "100%" } });
4125
+ }
4126
+ const customView = recorderViews?.find((v2) => v2.id === activeTab);
4127
+ return customView?.render ?? null;
4128
+ }, [activeTab, recorderViews, activeNarrativeEntries, activeNarrative, size]);
4116
4129
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4117
4130
  "div",
4118
4131
  {
@@ -4131,17 +4144,18 @@ function ExplainableShell({
4131
4144
  },
4132
4145
  "data-fp": "explainable-shell",
4133
4146
  children: [
4134
- tabs.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: {
4147
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: {
4135
4148
  display: "flex",
4136
4149
  borderBottom: `1px solid ${theme.border}`,
4137
4150
  background: theme.bgSecondary,
4138
- flexShrink: 0
4139
- }, children: tabs.map((tab) => {
4140
- const active = tab === activeTab;
4151
+ flexShrink: 0,
4152
+ overflowX: "auto"
4153
+ }, children: allTabs.map((tab) => {
4154
+ const active = tab.id === activeTab;
4141
4155
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4142
4156
  "button",
4143
4157
  {
4144
- onClick: () => handleTabChange(tab),
4158
+ onClick: () => handleTabChange(tab.id),
4145
4159
  style: {
4146
4160
  padding: "6px 14px",
4147
4161
  fontSize: 11,
@@ -4153,11 +4167,12 @@ function ExplainableShell({
4153
4167
  border: "none",
4154
4168
  borderBottom: active ? `2px solid ${theme.primary}` : "2px solid transparent",
4155
4169
  cursor: "pointer",
4156
- fontFamily: "inherit"
4170
+ fontFamily: "inherit",
4171
+ whiteSpace: "nowrap"
4157
4172
  },
4158
- children: tabLabels[tab]
4173
+ children: tab.name
4159
4174
  },
4160
- tab
4175
+ tab.id
4161
4176
  );
4162
4177
  }) }),
4163
4178
  /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { flex: 1, overflow: isNarrow ? "auto" : "hidden", display: "flex", flexDirection: "column" }, children: [
@@ -4195,17 +4210,7 @@ function ExplainableShell({
4195
4210
  ) })
4196
4211
  ] }),
4197
4212
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(HLinePill, { label: rightLabel, expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
4198
- rightExpanded && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { maxHeight: 250, flexShrink: 0, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4199
- DetailsContent,
4200
- {
4201
- snapshots: activeSnapshots,
4202
- selectedIndex: safeIdx,
4203
- narrativeEntries: activeNarrativeEntries,
4204
- narrative: activeNarrative,
4205
- size,
4206
- extraViews: recorderViews
4207
- }
4208
- ) }),
4213
+ rightExpanded && activeRecorderRender && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { maxHeight: 250, flexShrink: 0, overflow: "auto" }, children: activeRecorderRender({ snapshots: activeSnapshots, selectedIndex: safeIdx }) }),
4209
4214
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(HLinePill, { label: bottomLabel, detail: `${activeSnapshots.length} stages`, expanded: timelineExpanded, onClick: toggleTimeline }),
4210
4215
  timelineExpanded && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { flexShrink: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, size }) })
4211
4216
  ] })
@@ -4231,20 +4236,9 @@ function ExplainableShell({
4231
4236
  selectedIndex: safeIdx,
4232
4237
  onNodeClick: handleNodeClick
4233
4238
  }) }),
4234
- rightExpanded ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { width: "38%", minWidth: 300, maxWidth: 500, display: "flex", flexDirection: "row", overflow: "hidden" }, children: [
4239
+ rightExpanded && activeRecorderRender ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: { width: "38%", minWidth: 300, maxWidth: 500, display: "flex", flexDirection: "row", overflow: "hidden" }, children: [
4235
4240
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VLinePill, { label: rightLabel, expanded: true, onClick: () => toggleRight(false) }),
4236
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4237
- DetailsContent,
4238
- {
4239
- snapshots: activeSnapshots,
4240
- selectedIndex: safeIdx,
4241
- narrativeEntries: activeNarrativeEntries,
4242
- narrative: activeNarrative,
4243
- size,
4244
- fillHeight: true,
4245
- extraViews: recorderViews
4246
- }
4247
- )
4241
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: activeRecorderRender({ snapshots: activeSnapshots, selectedIndex: safeIdx }) })
4248
4242
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VLinePill, { label: rightLabel, expanded: false, onClick: () => toggleRight(true) })
4249
4243
  ] }),
4250
4244
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(HLinePill, { label: bottomLabel, detail: `${activeSnapshots.length} stages`, expanded: timelineExpanded, onClick: toggleTimeline }),