Getting started
The charts block is one component, <Charts />, that draws thirty-plus
chart types selected by the type prop. Everything but the data itself is
a flat, typed prop: verifiable by contract, reactive by construction.
Install
npm install @lemonadejs/charts@beta
import Charts from '@lemonadejs/charts';
import '@lemonadejs/charts/style.css';
The package has a single peer dependency: lemonadejs itself. No d3, no
canvas polyfills, nothing else arrives with it.
Your first chart
import Charts from '@lemonadejs/charts';
const series = [
{ name: 'Revenue', data: [120, 190, 80, 220] },
{ name: 'Cost', data: [80, 105, 130, 140] },
];
const App = () => html`<${Charts} type="bar"
categories="${['Q1', 'Q2', 'Q3', 'Q4']}"
series="${series}" legend labels title="Quarterly results" />`;The data definition
Two props carry all the data; everything else is presentation:
series:[{ name, data, color? }].datais a plain array of numbers for most types; specialty types accept richer points ([x, y]pairs for scatter,{ name, value }for pie/treemap/funnel,{ from, to, value }for sankey/chord).categories: the x-axis labels (bar/line), slice names (pie), or row/column labels (heatmap). Optional for types that carry names in their points.
The same pair drives every type, so switching from a bar to a line to a
stacked area is a one-word change, and since type is a live prop, it
can even happen at runtime.
Reactivity
Every declared prop arrives as a live state. Pass a plain value for a static chart, or pass a state for a live wire: assign to it and only the dependent parts of the scene rebuild:
import Charts from '@lemonadejs/charts';
const App = (props, { state }) => {
const series = state([{ name: 'Sales', data: [12, 19, 8, 22] }]);
const shuffle = () => {
series.value = [{ name: 'Sales',
data: series.value[0].data.map(() => Math.round(5 + Math.random() * 20)) }];
};
return html`<div>
<button onclick="${shuffle}">Randomize</button>
<${Charts} type="bar" categories="${['Q1', 'Q2', 'Q3', 'Q4']}"
series="${series}" labels />
</div>`;
};Note the v6 contract: assignment triggers, mutation does not. Build a
new array (or call .touch()) rather than pushing into the old one.
Three deployment forms
import { html, setComponents, createWebComponent } from 'lemonadejs';
import Charts from '@lemonadejs/charts';
html`<${Charts} />` // by value, no registration needed
setComponents({ Charts }); // register once, then <Charts /> by name
createWebComponent(Charts); // <lm-charts> for plain HTML or any framework
As a web component, attributes arrive as strings and are coerced to the
declared prop types; set rich values (arrays, objects) via
el.props = { series, categories }.
The contract
The machine-readable schema ships with the package, useful for tooling and for AI agents that generate charts:
import contract from '@lemonadejs/charts/contract.json';
verify.json in the package carries the conformance proof (111 checks)
produced by verify(Charts). See Contracts for how
the verification gate works.
Where next
- Bars, lines & areas: the cartesian family
- Pies & radial: slices, rings, gauges
- Hierarchy & flow: treemaps and sankeys
- Heatmap, bullet & more: the specialty types
- Palettes & colors: theming
- Annotations & axes: reference lines, formatting
- Interactivity & live data: events, drilldown, zoom