npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

footprint-explainable-ui

v0.18.1

Published

Themeable React components for visualizing FootPrint pipeline execution

Readme

footprint-explainable-ui

Themeable React components for visualizing footprintjs pipeline execution — time-travel debugging, flowchart overlays, subflow drill-down, and collapsible detail panels.

Install

npm install footprint-explainable-ui

Peer dependencies: react >= 18, react-dom >= 18

For flowchart components, also install:

npm install @xyflow/react

Entry Points

| Import path | What it provides | |---|---| | footprint-explainable-ui | Core components, themes, adapters | | footprint-explainable-ui/flowchart | Flowchart visualization (requires @xyflow/react) |

Quick Start

1. Convert execution data to snapshots

import { FlowChartExecutor } from "footprintjs";
import { toVisualizationSnapshots } from "footprint-explainable-ui";

const executor = new FlowChartExecutor(chart);
await executor.run({ input: data });

const snapshots = toVisualizationSnapshots(
  executor.getSnapshot(),
  executor.getNarrativeEntries(), // optional — enables rich narrative
);

2. Render with the all-in-one shell

import { ExplainableShell } from "footprint-explainable-ui";
import { TracedFlowchartView } from "footprint-explainable-ui/flowchart";

function DebugView({ snapshots, spec, narrative, narrativeEntries }) {
  return (
    <ExplainableShell
      snapshots={snapshots}
      spec={spec}
      narrative={narrative}
      narrativeEntries={narrativeEntries}
      title="My Pipeline"
      panelLabels={{ topology: "What Ran", details: "What Happened", timeline: "How Long" }}
      renderFlowchart={({ spec, snapshots, selectedIndex, onNodeClick }) => (
        <TracedFlowchartView
          spec={spec}
          snapshots={snapshots}
          snapshotIndex={selectedIndex}
          onNodeClick={onNodeClick}
        />
      )}
    />
  );
}

This gives you:

  • Flowchart (center) — execution path overlay, click subflow nodes to drill-down
  • Topology panel (left) — subflow tree navigator, collapsible via VLinePill handle
  • Details panel (right) — Memory state + Narrative tabs, collapsible
  • Timeline (bottom) — Gantt-style stage durations, collapsible
  • Time-travel slider — scrub through execution steps
  • Breadcrumbs — navigate back from subflow drill-down
  • Mobile responsive — auto-stacks vertically below 640px

3. Or compose individual components

import {
  TimeTravelControls,
  MemoryInspector,
  ScopeDiff,
  GanttTimeline,
  NarrativeTrace,
} from "footprint-explainable-ui";

function MyDebugger({ snapshots }) {
  const [idx, setIdx] = useState(0);
  const current = snapshots[idx];
  const previous = idx > 0 ? snapshots[idx - 1] : null;

  return (
    <>
      <TimeTravelControls
        snapshots={snapshots}
        selectedIndex={idx}
        onIndexChange={setIdx}
      />
      <MemoryInspector snapshots={snapshots} selectedIndex={idx} />
      <ScopeDiff
        previous={previous?.memory ?? null}
        current={current.memory}
        hideUnchanged
      />
      <NarrativeTrace narrative={snapshots.map(s => s.narrative)} />
      <GanttTimeline snapshots={snapshots} selectedIndex={idx} onSelect={setIdx} />
    </>
  );
}

ExplainableShell

The all-in-one orchestrator. Handles time-travel, subflow drill-down, memory/narrative panels, and responsive layout.

Props

| Prop | Type | Default | Description | |---|---|---|---| | snapshots | StageSnapshot[] | required | Visualization snapshots | | spec | SpecNode \| null | — | Pipeline spec (enables flowchart + subflow tree) | | title | string | "Flowchart" | Breadcrumb root label | | narrative | string[] | — | Flat narrative lines | | narrativeEntries | NarrativeEntry[] | — | Structured narrative (rich rendering) | | panelLabels | PanelLabels | { topology: "Topology", details: "Details", timeline: "Timeline" } | Customize collapsible pill labels | | defaultExpanded | DefaultExpanded | { details: true } | Which panels start open | | tabs | ShellTab[] | ["result", "explainable"] | Visible tabs | | renderFlowchart | (props) => ReactNode | — | Flowchart renderer (pass TracedFlowchartView) | | resultData | Record<string, unknown> | — | Final output data for Result tab | | size | "compact" \| "default" \| "detailed" | "default" | Size variant | | unstyled | boolean | false | Strip styles, render data-fp attributes |

Panel Labels

Customize the text on collapsible pill buttons. Semantic keys — not tied to position:

<ExplainableShell
  panelLabels={{
    topology: "What Ran",      // left panel (subflow tree)
    details: "What Happened",  // right panel (memory/narrative)
    timeline: "How Long",      // bottom panel (Gantt)
  }}
/>

Default Expanded

Control which panels start open. Desktop default: details panel open (flowchart + memory = the library's unique value). For mobile, pass all false:

// Desktop (default) — memory panel open
<ExplainableShell snapshots={...} spec={...} />

// Mobile — all collapsed, flowchart fills screen
<ExplainableShell
  snapshots={...}
  defaultExpanded={{ details: false }}
/>

// Everything open
<ExplainableShell
  snapshots={...}
  defaultExpanded={{ topology: true, details: true, timeline: true }}
/>

Responsive Layout

The shell auto-detects container width via ResizeObserver:

  • Desktop (≥640px): 3-column layout — SubflowTree | Flowchart | Memory/Narrative. Side panels collapse to VLinePill handles.
  • Mobile (<640px): Stacked vertical — Flowchart (350px) → collapsible HLinePill sections. All panels auto-collapse on narrow.

Collapsible Panel UX

All panels use the line + pill pattern:

  • Collapsed: Thin divider line with a centered pill button (label + arrow)
  • Expanded: Full content with a pill handle on the closing edge
  • VLinePill (left/right panels): Vertical line with centered vertical pill. side prop controls arrow direction.
  • HLinePill (bottom timeline): Horizontal line with centered pill.

Flowchart Visualization

Import from footprint-explainable-ui/flowchart:

TracedFlowchartView (recommended)

Self-contained flowchart renderer. Handles overlay computation, auto-fitView on resize.

import { TracedFlowchartView } from "footprint-explainable-ui/flowchart";

<div style={{ height: 400 }}>
  <TracedFlowchartView
    spec={spec}
    snapshots={snapshots}
    snapshotIndex={idx}
    onNodeClick={(nodeId) => handleClick(nodeId)}
  />
</div>

Without snapshots, renders a plain static flowchart. With snapshots, shows the execution trace path with Google Maps-style glow.

Auto-fitView: The flowchart automatically calls fitView() when its container resizes (e.g. panel expand/collapse).

Manual control with specToReactFlow

import { specToReactFlow, StageNode, type ExecutionOverlay } from "footprint-explainable-ui/flowchart";
import { ReactFlow } from "@xyflow/react";

const overlay: ExecutionOverlay = {
  doneStages: new Set(["LoadOrder", "ProcessPayment"]),
  activeStage: "ShipOrder",
  executedStages: new Set(["LoadOrder", "ProcessPayment", "ShipOrder"]),
  executionOrder: ["LoadOrder", "ProcessPayment", "ShipOrder"],
};

const { nodes, edges } = specToReactFlow(spec, overlay);

<ReactFlow
  nodes={nodes}
  edges={edges}
  nodeTypes={{ stage: StageNode }}
  fitView
/>

Theming

CSS Variables (recommended)

Consumer controls theme via --fp-* CSS custom properties. Components use var(--fp-*, fallback):

:root {
  --fp-color-primary: #7c6cf0;
  --fp-bg-primary: #1e1a2e;
  --fp-bg-secondary: #2a2540;
  --fp-bg-tertiary: #3a3455;
  --fp-text-primary: #f0e6d6;
  --fp-text-secondary: #b0a898;
  --fp-text-muted: #6b6b80;
  --fp-border: #3a3455;
  --fp-radius: 8px;
  --fp-font-sans: 'Inter', system-ui, sans-serif;
  --fp-font-mono: 'JetBrains Mono', monospace;
}

ThemeProvider

import { FootprintTheme, warmDark } from "footprint-explainable-ui";

<FootprintTheme tokens={warmDark}>
  <MyApp />
</FootprintTheme>

Built-in Presets

| Preset | Description | |---|---| | coolDark | Default — indigo/slate dark theme | | warmDark | Charcoal-purple with warm text | | warmLight | Cream/peach light theme | | coolLight | Light indigo theme |


Components Reference

Core Components

| Component | Description | |---|---| | ExplainableShell | All-in-one orchestrator with collapsible panels and responsive layout | | TimeTravelControls | Play/pause, prev/next, scrubber timeline | | MemoryPanel | Memory state + scope diff (composite right-panel view) | | NarrativePanel | Narrative trace with progressive reveal | | StoryNarrative | Rich rendering of structured NarrativeEntry[] | | NarrativeTrace | Collapsible stage groups with progressive reveal | | NarrativeLog | Simple timeline-style execution log | | ScopeDiff | Side-by-side scope changes (added/changed/removed) | | ResultPanel | Final pipeline output + console logs | | MemoryInspector | Accumulated memory state viewer | | GanttTimeline | Horizontal duration timeline (collapsible) | | SnapshotPanel | All-in-one inspector (scrubber + memory + narrative + Gantt) |

Flowchart Components (footprint-explainable-ui/flowchart)

| Export | Description | |---|---| | TracedFlowchartView | Self-contained flowchart with trace overlay and auto-fitView | | FlowchartView | Lower-level ReactFlow wrapper | | StageNode | Custom node with state-aware coloring, step badges, pulse rings | | specToReactFlow | Convert pipeline spec → ReactFlow nodes/edges with overlay | | SubflowBreadcrumb | Breadcrumb bar for subflow drill-down | | SubflowTree | Tree view of all subflows (used in shell's left panel) |

Adapters

| Export | Description | |---|---| | toVisualizationSnapshots | Convert FlowChartExecutor.getSnapshot()StageSnapshot[] | | subflowResultToSnapshots | Convert subflow result → StageSnapshot[] | | createSnapshots | Build StageSnapshot[] from simple arrays (testing/custom data) |

Types

| Export | Description | |---|---| | PanelLabels | { topology?, details?, timeline? } — pill label customization | | DefaultExpanded | { topology?, details?, timeline? } — initial panel state | | StageSnapshot | Core snapshot type for all components | | NarrativeEntry | Structured narrative entry with type/depth/stageName |


Size Variants

All components accept a size prop: "compact", "default", or "detailed".

<GanttTimeline snapshots={snapshots} size="compact" />
<MemoryInspector snapshots={snapshots} size="detailed" />

Unstyled Mode

Strip all built-in styles for full CSS control. Components render semantic data-fp attributes:

<NarrativeTrace narrative={lines} unstyled className="my-narrative" />
[data-fp="narrative-header"] { font-weight: bold; }
[data-fp="narrative-step"] { padding-left: 2rem; }

License

MIT