@cyberiasoftware/pivot
v0.1.8
Published
Cyberia native React pivot table with SVG charts, histogram, and exploration UX
Maintainers
Readme
@cyberiasoftware/pivot
React pivot table with native charts, histogram / box / violin views, and an exploration panel for drag-and-drop analysis.
Install
npm install @cyberiasoftware/pivotPeer dependencies: react and react-dom (^18 or ^19).
Quick start
CSV/TSV path (fetched and parsed in the browser):
import { CyberiaPivotPanel } from "@cyberiasoftware/pivot";
import "@cyberiasoftware/pivot/styles.css";
export function App() {
return <CyberiaPivotPanel data="./data/Supermarket_sales.csv" cacheKey="demo" />;
}Or pass an in-memory matrix / array of objects:
const matrix = [
["Region", "Sales"],
["East", 120],
["West", 80],
];
<CyberiaPivotPanel data={matrix} cacheKey="demo" />CyberiaPivotPanel
Exploration panel built on PivotTableUI:
- Drag-and-drop rows/columns with show/hide controls
- Renderer combobox always available (including when controls are hidden)
- Session cache via
cacheKey(survives remounts until page refresh) - Hover highlights plus multi-pin row/column highlights (click headers to pin/unpin; Clear pins removes all)
- Table alignment (left / center / right) when controls are hidden
- Chart sizing + fullscreen
- Native chart modebar (download PNG, zoom in/out, reset view; pan when zoomed)
- TSV download when using Exportable TSV
- Table + native SVG charts (including Histogram, Box Plot, Violin)
- Optional CSV number normalization (
$, commas) when loading from path - Dark theme via CSS variables or built-in
className="cp-theme-dark"
Props
| Prop | Type | Description |
|------|------|-------------|
| data | matrix, objects, callback, or CSV/TSV path/URL | Pivot input. Paths are fetched and parsed inside the panel. |
| initialState | Partial<CyberiaPivotSnapshot>? | Restore rows/cols/vals/aggregator/renderer from history. |
| onStateChange | (snapshot) => void | Persist durable pivot config whenever it changes. |
| cacheKey | string? | Persist pivot UI state across remounts for this key. |
| renderers | Record<string, ComponentType>? | Extra/override renderers merged onto defaults. |
| normalizeCsvNumbers | boolean? | Strip $ / commas from numeric CSV cells (default true). |
| renderToolbar | (ctx) => ReactNode | Customize toolbar; return null to hide. |
| className | string? | Extra class on the root (e.g. cp-theme-dark). |
Low-level API
import { useState } from "react";
import { PivotTableUI, DefaultRenderers, aggregators } from "@cyberiasoftware/pivot";
import "@cyberiasoftware/pivot/styles.css";
function App({ data }) {
const [state, setState] = useState({});
return (
<div className="cyberia-pivot">
<PivotTableUI
data={data}
onChange={setState}
renderers={DefaultRenderers}
aggregators={aggregators}
{...state}
/>
</div>
);
}Also exported: PivotTable, TableRenderers, ChartRenderers, Dropdown, DraggableAttribute, aggregators/utilities (parseCsv, loadCsvMatrix, normalizeNumericCells, …), plus toPivotSnapshot / snapshotToPivotState.
Save / restore (chat history)
Store the CSV path (or your own data id) plus a CyberiaPivotSnapshot — not the full matrix. Snapshot includes rows, cols, vals, aggregatorName, rendererName, filters, sort order, and optional panel chrome.
type SavedPivot = {
dataPath: string;
pivot: CyberiaPivotSnapshot;
};
// Save while exploring
<CyberiaPivotPanel
data={saved.dataPath}
initialState={saved.pivot}
onStateChange={(pivot) =>
updateMessage({ dataPath: saved.dataPath, pivot })
}
/>
// Restore from history — remount so initialState applies cleanly
<CyberiaPivotPanel
key={messageId}
data={message.dataPath}
initialState={message.pivot}
onStateChange={(pivot) => updateMessage({ ...message, pivot })}
/>onStateChange is the callback to wire into genai persistence. Session cacheKey is only for same-page remounts; for conversation history use initialState + key.
Charts (native SVG)
Available chart renderers:
| Renderer | Data | |----------|------| | Grouped/Stacked Column & Bar, Line, Dot, Area, Scatter, Multiple Pie | Aggregated pivot cells | | Histogram | Raw numeric samples from the first vals field (or first numeric column) | | Box Plot / Violin | Same raw-value sampling; group by rows when set |
For Histogram / Box / Violin, pick a numeric field (switch aggregator to Sum or Average so the value dropdown appears).
Theming
Option A — built-in dark palette:
<CyberiaPivotPanel data={data} className="cp-theme-dark" />Option B — host design tokens (e.g. cyberia-genai / next-themes): remap under .dark (or your theme selector). The package also applies dark pin/crosshair accents when nested under .dark.
.cyberia-pivot {
--cp-fg: hsl(var(--foreground));
--cp-bg: hsl(var(--background));
--cp-muted: hsl(var(--muted));
--cp-muted-fg: hsl(var(--muted-foreground));
--cp-border: hsl(var(--border));
--cp-border-soft: hsl(var(--border));
--cp-popover: hsl(var(--popover));
--cp-popover-fg: hsl(var(--popover-foreground));
--cp-primary: hsl(var(--primary));
}
.dark .cyberia-pivot {
--cp-border-soft: hsl(var(--input));
/* optional overrides — package defaults dark pin/crosshair when under .dark */
--cp-crosshair-fg: #ecfdf5;
}Useful interaction tokens: --cp-col-pin, --cp-col-pin-outline, --cp-crosshair, --cp-crosshair-fg.
Heatmap cells keep dark ink on pale red (readable in both themes). Tables, charts, modebar, and pins all follow --cp-*.
Migrating from cyberia-genai
- Swap
CsvPivotPanelforCyberiaPivotPanel. - Import
@cyberiasoftware/pivot/styles.cssand drop the.csv-pivot-panelCSS block. - Pass CSV as a path string, or keep your own parse and pass a matrix / objects to
data.
Development
npm install
npm run build
npm run exampleExample app: http://localhost:5177/
Publishing (GitHub Actions → npm)
Uses npm Trusted Publishing (OIDC — no long-lived npm token).
- Push this repo to GitHub (e.g.
cyberia-software/sdk-pivot). - On npm → package Settings → Trusted Publisher:
- Organization or user:
cyberia-software - Repository:
sdk-pivot - Workflow filename:
publish.yml - Check Allow npm publish → Set up connection
- Organization or user:
- In GitHub → Actions → Publish → Run workflow → choose
patch/minor/major.
The workflow bumps package.json version, builds, publishes to npm, then pushes the version commit + v* tag.
Note: npm provenance needs a public GitHub repo. This workflow publishes without provenance so a private sdk-pivot works. Make the repo public later if you want provenance attestations.
License
MIT
