chart
Pure server-side data-to-SVG chart pack: render arbitrary data into standalone, themeable SVG charts with zero dependencies. Supports bar (vertical/horizontal), line, area (with smoothing), pie...
chart — pure data→SVG chart pack
Server-side data visualization with zero npm dependencies (Node built-ins only). Feed it plain data, get back a complete, standalone <svg> string you can inline, embed in an email or PDF, drop into a dashboard/report, or turn into an <img> data URI. Deterministic, framework-agnostic, and themeable.
Tools (17)
| Tool | Input shape | What it draws |
|---|---|---|
bar | [n] · [{label,value}] · {label:value} | Vertical (or options.horizontal) bar chart with nice axes |
line | numeric series · multi-series | Line chart, optional smooth, showPoints, multi-series legend |
area | numeric series · multi-series | Filled area chart (single or overlaid) |
pie | categories | Pie chart with % labels + legend |
donut | categories | Donut (ring) chart; supports centerLabel/centerSubLabel |
sparkline | numeric series | Tiny inline trend line (no axes), optional min/max markers |
gauge | number or {value,min,max} | Semicircular gauge/dial with value readout + zones |
scatter | [{x,y}] · [[x,y]] · {series} | Scatter/bubble plot (r sizes bubbles), numeric x/y axes |
stackedBar | multi-series | Stacked bar chart |
groupedBar | multi-series | Grouped/clustered bar chart |
histogram | numeric series | Auto-binned frequency histogram (options.bins) |
radar | multi-series (≥3 axes) | Radar/spider chart |
heatmap | 2D matrix · {values,rows,cols} | Color-graded heatmap/matrix (lowColor/highColor) |
progress | categories | Horizontal progress bars (options.percent) |
bullet | {value,target,max,bands} | Bullet chart (value vs target across qualitative bands) |
toDataUri | { svg } | SVG string (or chart result) → data:image/svg+xml URI |
palette | { name? } | Return a named color ramp (or all) for options.colors |
Every rendering tool takes one args object { data, options } and returns { svg, width, height }. An HTTP POST body maps 1:1 onto the call.
Theming (options)
colors: []— series palette, orpalette: 'ocean'(a named ramp — seepalettetool).width,height,title,titleColor,background,rounded.padding— a number, or{ top, right, bottom, left }.- Per-chart toggles:
showValues,showLegend,showGrid,showPoints,smooth(line/area),
horizontal (bar), innerRadius/centerLabel (donut), bins (histogram), min/max (gauge/heatmap/bullet), unit/label/zones (gauge), target/bands (bullet), lowColor/highColor (heatmap), percent (progress), strokeWidth.
Named palettes: default, vivid, ocean, sunset, forest, mono, warm, cool.
Usage
import chart from './index.js';
// Simple bar chart
const { svg } = chart.adapters.bar({
data: [{ label: 'Q1', value: 120 }, { label: 'Q2', value: 180 }, { label: 'Q3', value: 90 }],
options: { title: 'Quarterly Revenue', palette: 'ocean', height: 320 },
});
// Multi-series line with smoothing
chart.adapters.line({
data: { categories: ['Jan', 'Feb', 'Mar'], series: [
{ name: 'Web', values: [10, 22, 18] },
{ name: 'iOS', values: [5, 9, 14] },
]},
options: { smooth: true, showPoints: true },
});
// Embed anywhere as an <img>
const { dataUri } = chart.adapters.toDataUri({ svg });
// `<img src="${dataUri}">` — works in email, PDF, static HTML
// KPI donut with center label
chart.adapters.donut({ data: { Done: 72, Todo: 28 }, options: { centerLabel: '72%', centerSubLabel: 'complete' } });
// List a palette to reuse as options.colors
chart.adapters.palette({ name: 'sunset' }); // → { name, colors: [...] }
DRY boundary
No generic charting existed in Leumas2 before this pack. The only prior SVG-plotting code lives in domain/a-physics (plot), but that is physics-specific: it sweeps a physics formula's variable to draw a function curve (formula-driven, domain-bound). This pack charts arbitrary caller-supplied data (categories / series / points / matrices / KPIs) with no concept of formulas or physics — reusable across emails, PDFs, dashboards, and reports.
Rule of thumb: physics plot graphs a function; chart graphs data. Keep them separate.
The tidy internal SVG builder (element/text helpers, linear + "nice" scales, color interpolation, palettes) is deliberately dependency-free and framework-agnostic. It may later graduate to a shared @leumas util; until then it stays self-contained here per the pack contract (no cross-pack imports).
Notes
- Pure & deterministic — no randomness, no clock, no I/O. Same input → same SVG.
- All user text is XML-escaped; output is a JSON-serializable
{ svg }. - Sane defaults: a bare
{ data }call renders a themed chart;optionsonly refine it.