|
|
4 months ago | |
|---|---|---|
| .. | ||
| test | 4 months ago | |
| README.md | 4 months ago | |
| array.ts | 4 months ago | |
| curve.ts | 4 months ago | |
| index.ts | 4 months ago | |
| path.ts | 4 months ago | |
| scale-band.ts | 4 months ago | |
| scale-linear.ts | 4 months ago | |
| scale-time.ts | 4 months ago | |
| shape-arc.ts | 4 months ago | |
| shape-line.ts | 4 months ago | |
| shape-stack.ts | 4 months ago | |
| ticks.ts | 4 months ago | |
| types.ts | 4 months ago | |
README.md
plots — charting math engine
Pure, dependency-free primitives for building charts: scales (data → pixels), shape generators (points → SVG paths), tick generation and small statistics helpers. No DOM, no framework, no state — just functions. The UIX chart components consume this; the engine knows nothing about them.
Like the other libs/ modules it depends on nobody: every algorithm here
(linear/band/time scales, 1-2-5 "nice" ticks, monotone cubic interpolation,
arc geometry) is implemented from the underlying mathematics, not ported from
any external library.
Why a lib (and not an art)
The math is pure functions with no runtime state and no CSS emission — the exact
contract of libs/. Reactivity belongs in the consuming soma layer (a provider
recomputes a fresh scale when its inputs change), mirroring how chronos/engine
keeps pure layout modules separate from its reactive state.svelte.ts.
Surface
| Module | Exports | Purpose |
|---|---|---|
scale-linear |
scaleLinear |
Continuous data → pixels (value axes) |
scale-band |
scaleBand, scalePoint |
Categories → bands (bars) / points (line·scatter) |
scale-time |
scaleTime |
Epoch-ms → pixels with calendar-aware ticks |
ticks |
ticks, tickStep, nice |
"Nice" round tick values for an axis |
array |
extent, min, max, sum, range, bisect*, bisector |
Stats + nearest-datum lookup (hover) |
shape-line |
line, area |
Polyline / filled-band SVG paths |
shape-arc |
arc, pie |
Pie / donut / gauge geometry + slice layout |
shape-stack |
stack |
Stacked baselines (stacked bar / area) |
curve |
curveLinear, curveMonotoneX, curveStep, curve(name) |
Point-connection strategies |
path |
fmt, coord |
Coordinate formatting for custom shapes |
Conventions
- Pixel space. Scales map data → pixels; shape generators take points that are already in pixels. This decouples shapes from scales (compositional).
- Immutable scales.
scaleLinear(config)returns a callable whosedomain/rangeare frozen and whose.nice()returns a new scale — derive a fresh scale on input change, never mutate in place (suits Svelte runes). - Angles (arc/pie):
0points up (12 o'clock), increasing clockwise. - Time works on epoch milliseconds; a
DateValueconsumer converts at its edge so this module carries no date dependency.
Example
import { line, scaleLinear } from '$libs/plots'
const x = scaleLinear({ domain: [0, 5], range: [0, 300] })
const y = scaleLinear({ domain: [0, 100], range: [150, 0] }) // y axis is inverted
const data = [10, 40, 30, 80, 60, 90]
const d = line(data.map((value, i) => ({ x: x(i), y: y(value) })))
// → "M0,135L60,90L120,105L180,30L240,60L300,15"
Tests
npx vitest run src/libs/plots — 36 cases across array / ticks / scale /
shape, asserting the math against known values.