# chart — pure data→SVG chart pack

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...


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, **or** `palette: 'ocean'` (a named ramp — see `palette` tool).
- `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

```js
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; `options` only refine it.


---
Source: shared/engines/adapters/domain/chart/README.md
Canonical: https://docs.leumas.tech/p/adapters/domain/chart
