Skip to content

Data & Configuration

Start with Installation if Charts is not yet installed. This guide follows a chart from its first rows through configuration, updates, interaction, exports and cleanup.

For dedicated interactive examples of drawing, navigation, linking, selection, exports and other shared features, see Chart tools.

For calculated overlays, calendar-aware comparisons, forecasts, faceting and performance comparisons, see the separate Analysis guide. These tools preserve source observations and use explicit statistical policies.

Switch chart type, update rows, turn value labels or grid lines on and off, and export the result. The example uses only the two registered chart definitions.

Loading chart…

Give the host an explicit height, then call the factory after the host is mounted. No stylesheet or custom element registration is required.

<div id="revenue-chart" style="width: 100%; height: 360px;"></div>
import { createLineChart } from '@revolist/charts/line';
const container = document.getElementById('revenue-chart')!;
const chart = await createLineChart({
container,
data: [
{ month: 'Jan', revenue: 120 },
{ month: 'Feb', revenue: 180 },
{ month: 'Mar', revenue: null },
],
mapping: {
category: { field: 'month' },
series: [{ field: 'revenue', label: 'Revenue' }],
},
presentation: { title: 'Monthly revenue' },
});
// Later, when your application removes the host:
// chart.destroy();

Each row becomes one category. Values must be finite numbers or explicit null; missing values and numeric strings are rejected. Category keys must be unique by type and value. The converter preserves identities and does not aggregate rows. Use category.label to map a separate string display-label field.

Use presentation for titles, legend placement, axis titles and value labels. Use chartOptions for the selected type’s options. Supported options and their ranges are declared by that type’s definition; an unsupported option is rejected.

await chart.update({
presentation: {
title: 'Monthly revenue',
subtitle: 'Actual revenue · € thousands',
legendPosition: 'bottom',
yAxisTitle: '€ thousands',
dataLabels: true,
},
chartOptions: { showGridLines: false },
theme: 'dark',
});

Presentation is replaced as a whole, so include titles you want to retain. To edit an existing chart while keeping other presentation settings:

await chart.update({
presentation: { ...chart.model.presentation, dataLabels: true },
});

Use explicit datasets and channel bindings

Section titled “Use explicit datasets and channel bindings”

Rows are convenient for simple categorical charts. Use createChartDataset to reuse a conversion, or supply a complete ChartDataset from your own analytical pipeline. Channel bindings reference series IDs, not display labels:

import { createScatterChart } from '@revolist/charts/scatter';
const scatter = await createScatterChart({
container,
data: [
{ product: 'A', cost: 20, revenue: 60 },
{ product: 'B', cost: 35, revenue: 90 },
],
mapping: {
category: { field: 'product' },
series: [{ field: 'cost' }, { field: 'revenue' }],
},
bindings: { x: ['cost'], y: ['revenue'] },
});
scatter.destroy();

Hierarchy charts require hierarchy metadata. Box plots and violins require observations or valid distribution summaries; aggregate totals cannot recover a distribution. Financial charts need explicit OHLC channels. The overview’s live catalog exposes a valid dataset and bindings for every built-in type.

Updates reuse the last successful field mapping. Await an update before reading a snapshot or exporting. Invalid updates preserve the previous chart.

await chart.update({
data: [
{ month: 'Apr', revenue: 240 },
{ month: 'May', revenue: 210 },
],
});
await chart.update({ interaction: { mode: 'select' } });
// Clicking a point now commits local selection.
await chart.clearSelection();
const csv = chart.getCSV();
await chart.download({ fileFormat: 'svg', fileName: 'monthly-revenue' });
// PNG, CSV and raster PDF downloads are also supported by the native renderer.

Presentation updates replace that settings object. Include titles and other presentation settings you want to keep. undefined preserves a setting owner; {} resets it and arrays replace it.

Per-type imports such as /line, /grouped-column, /pie and /box-plot expose a definition and a bound factory, for example lineChart and createLineChart. A bound factory keeps its chart type fixed.

For an application that switches types, register only the definitions it needs with createChartFactory from /core. Here is the actual setup used by the live example above. Save it as revenue-chart.ts:

import { createChartFactory } from '@revolist/charts/core';
import { lineChart } from '@revolist/charts/line';
import { groupedColumnChart } from '@revolist/charts/grouped-column';
export const revenueRows = [
{ month: 'Jan', revenue: 120, costs: 80 },
{ month: 'Feb', revenue: 180, costs: 110 },
{ month: 'Mar', revenue: 160, costs: 95 },
{ month: 'Apr', revenue: 240, costs: 140 },
{ month: 'May', revenue: 210, costs: 125 },
{ month: 'Jun', revenue: 290, costs: 165 },
];
// Register only the types this application needs.
const createRevenueChart = createChartFactory([lineChart, groupedColumnChart]);
export function mountRevenueChart(
container: HTMLElement,
theme: 'light' | 'dark' = 'light',
signal?: AbortSignal,
) {
return createRevenueChart({
container,
signal,
theme,
chartType: 'line',
data: revenueRows,
mapping: {
category: { field: 'month' },
series: [
{ field: 'revenue', label: 'Revenue' },
{ field: 'costs', label: 'Costs' },
],
},
presentation: {
title: 'Monthly performance',
subtitle: 'Illustrative data · € thousands',
legendPosition: 'bottom',
yAxisTitle: '€ thousands',
},
interaction: { mode: 'select' },
});
}

The returned controller supports both registered types:

import { mountRevenueChart } from './revenue-chart';
const container = document.getElementById('revenue-chart')!;
const chart = await mountRevenueChart(container);
await chart.update({ chartType: 'groupedColumn' });
await chart.update({ chartType: 'line' });
chart.destroy();

The package-root createChart includes the full built-in catalog when arbitrary type switching is needed. Specialized charts retain their data requirements: for example, scatter charts need channel bindings and box plots need source observations or valid distribution summaries. Supply an explicit ChartDataset for analytical data, hierarchy metadata, bindings or distributions. createChartDataset from /core also converts rows separately for reuse.

Every per-type factory also accepts rendererOptions directly. See Chart Customization for all color, label, element-style and advanced SVG controls, including Pivot and geographic usage.

Pass a renderer to a bound factory when your application supplies theme tokens, a palette, or label formatting. This example still loads only the line renderer:

import { createNativeChartsRenderer } from '@revolist/charts/core';
import { createLineChart, lineChart } from '@revolist/charts/line';
const chart = await createLineChart({
container,
data: [{ month: 'Jan', revenue: 120 }],
mapping: { category: { field: 'month' }, series: [{ field: 'revenue' }] },
renderer: createNativeChartsRenderer([lineChart], {
palette: ['#6647f0', '#fd7e14'],
theme: { foreground: '#172033', grid: '#e2e8f0' },
}),
localeText: { dataTable: { categoryHeader: 'Month' } },
});
chart.destroy();

Set theme: 'light' or 'dark' to follow your application’s theme, or pass renderer theme tokens through a custom renderer. theme: 'auto' follows the nearest host data-theme attribute, falling back to the system color preference. Configure labels and titles with presentation, per-type settings with chartOptions, and translations with localeText.

const saved = JSON.stringify(chart.model);
chart.destroy();
const restored = await createLineChart({
container,
model: JSON.parse(saved),
});
// Dispose when your component unmounts or route changes.
restored.destroy();

Chart models are version 1 and contain chart state. Pass either rows with a mapping, an explicit dataset, or a saved model. A supplied AbortSignal cancels pending creation and disposes the chart when aborted. Always destroy a chart when its host unmounts; destroy() is idempotent.

  • @revolist/charts/echarts accepts an application-supplied ECharts runtime.
  • @revolist/charts/vector-pdf accepts a vector PDF encoder runtime.
  • @revolist/charts/geographic provides opt-in geographic capability packs with application-supplied providers and assets.

For linked charts built from grouped grid results, queries, drill-down or filter synchronization, use Pivot Charts. Pivot consumes the same chart engine and owns those grid-specific operations.

Axes & number formatting documents numeric X (linear, log, symlog, sqrt), level/category-ID data mappings, placement/reversal/ticks, xAxes/yAxes, per-series assignments, grouped categories, measured gutters and Pivot authoring. Settings remain subject to each catalog definition’s capabilities.

Use Sankey graph data for general DAG inputs, sort/layout controls, colors, labels, callbacks and controlled highlights. Heatmap navigation covers independent row/column windows and navigator tracks.

For dense native line/area and combination paths, chartOptions.sampling selects 'auto', 'none', 'm4', 'minmax', or 'lttb' without modifying raw data or domains. The option persists in the model and is shared with Pivot.

For native line/area and combination categorical X axes, choose axes.x.categoryPlacement (or axes.xAxes[id].categoryPlacement) as 'point' or 'band'. Omit it to keep the chart family default; it does not change raw category IDs or values.

Candlestick and OHLC role bindings can contain parallel arrays for multiple groups. Open/high/low helpers can broadcast, while each close field uniquely owns its group and X/Y assignments. See candlestick and OHLC collections. Volume-price adds one distinct paired volume measure per close owner and keeps shared price/volume Y roles.

A ChartRef returned by the root, registered, or per-type factory exposes the same lifecycle. A per-type factory restricts chartType updates to its type.

MemberPurpose and lifetime
model, getDataset()Independent snapshots of committed state/canonical loaded data. Mutating a snapshot does not update the chart.
capabilitiesActive renderer contract, including supported types, interaction modes, image data URLs and download formats; also check the catalog type’s feature support.
update(patch)Validated asynchronous data/settings update. Nested setting owners replace rather than deep merge. Runtime callbacks and rendererOptions are creation options, not update patches.
applyTransaction({ add?, update?, remove?, addIndex? })Atomic row changes by category-field identity; see live data.
setSelection(targets), clearSelection()Commit semantic source selection; see selection.
setRangeSelection(rangeOrNull), clearRangeSelection()Enable/set or clear the authored axis interval without dropping retained styling; see range selection.
setDataSource(source?), reloadData()Attach, detach or refresh the asynchronous data owner; see async data.
subscribe(listener)Observe committed model snapshots; returns an idempotent unsubscribe. It does not synthesize a first event or report animation frames.
getCSV(options?), download(options?), getImageDataURL(options?)Synchronous data serialization or asynchronous file/PNG capture; see all export options.
focus()Focus the native chart’s accessible inspection surface where supported.
id, getSyncSnapshot(), subscribeEvents(), applyViewport(), applySyncState()Provider-facing linking contract. Prefer createChartSyncGroup to hand-written propagation; see chart linking.
destroy()Idempotent cleanup of renderer, listeners, data requests and subscriptions; later operations reject.

Creation options also include chartId for stable chart identity, signal for creation/lifetime cancellation and localeText for UI/formatting. Do not pass these through update. Reattach runtime values when restoring a saved model.

Creation callbackReceives / when it runs
onNodeClick(detail)Canonical category, series and raw value; relationship points also expose bound channelValues/channelSeries. Native user activation can include originalEvent. Aggregate inspection does not invent source records.
onChange(model)A committed model snapshot after an accepted change. Notification failures do not undo a committed model or block other subscribers.
onViewportChange(viewport, origin)Committed public windows and 'pointer', 'keyboard', 'api' or 'calendar' origin.
onHoverChange(hover)Transient source-coordinate hover used by linking; separate from saved selection.
onSelectionRequest(selection)Semantic targets requested by interaction.mode: 'event'; the host decides whether to commit them.
onRangeSelectionStart, onRangeSelectionChange, onRangeSelectionEndAxis-range gesture lifecycle with public range/origin context; see the range-selection guide.
underlyingRecordsRuntime source-record provider, not model data; see underlying records.
onReloadDataInherited low-level host callback. Public factories route Retry to their own reloadData() source runtime and do not invoke a caller-supplied replacement. Use dataSource.load / reloadData for application refresh.
onError(error)Runtime/notification failures. Also catch rejected creation/update/export promises; validation may throw ordinary TypeError/RangeError as well as ChartError.
exportHooks, onBeforeDownload, onDownloadedExport operation lifecycle and synchronous legacy veto/notification; see export hooks.

parseChartModel and cloneChartModel from /core parse/own saved model values; assertChartDataset validates a canonical dataset. These utilities do not mount a chart or establish backend support: creation still validates the complete selected type/settings/renderer combination. chartDimensionFieldId(axis, field) provides the stable field ID for generated analytical-frame dimensions.

limits persists declared input budgets, independently of rendering policy and path sampling. Standalone creation resolves defaults to 10,000 categories, 250 series and 50,000 category × series cells. DEFAULT_CHART_LIMITS exported from /core is the shared base (1,000, 250, 50,000); hosts such as Pivot can apply their own category policy. Supply all overrides explicitly when comparing hosts or reproducing dense-renderer benchmarks.

const chart = await createChart({ container, chartType: 'scatter', dataset, bindings,
limits: { maxCategories: 100_000, maxSeries: 4, maxDataPoints: 400_000 } });

Only maxCategories, maxSeries and maxDataPoints are accepted. Values must be finite, at least one and normalize to a safe integer; fractional values are floored. Cell limits include null matrix cells, not just painted observations. Distribution/histogram metadata also obeys the source validation budgets. Exceeding a budget rejects with ChartError.code === 'LIMIT_EXCEEDED' and count/ limit details. Invalid budgets reject before replacing the accepted frame. Increasing a limit does not promise a frame rate, GPU availability, one mark per source observation or more browser memory; use the renderer performance guides for measured host-specific limits.

columnLine and areaLine also support explicitly bound bubble and histogram layers through the existing combination owner. Sample-owned X differs from the chart’s category-owned line/column X; complete histogram summaries do not invent loaded records. See Cartesian bubble and histogram layers for every channel, named-axis assignment, layer order, shared tooltip, async source, inspector and export rule. This does not add arbitrary type composition.

mapping and createChartDataset(rows, mapping) share the same contract. One row becomes one category; conversion does not aggregate, coerce numeric strings or group duplicate keys.

Mapping fieldMeaning
category.fieldRequired source field for a unique finite string/number/boolean/null identity. Numeric -0 and 0 share identity. Duplicate keys reject; changing a label does not change identity.
category.labelOptional field name whose row value is the display string, not a literal label. Omission uses the final path value.
category.pathOptional nonempty list of unique hierarchy field names, at most 128. Path values must be finite typed scalars/null. It cannot be combined with parent.
category.parentOptional parent-ID field for organization hierarchy. Every nonnull referenced parent must exist; cycles and chains exceeding 128 levels reject.
category.subtitle, category.imageOptional source field names for organization card metadata. Nonmissing values must be strings; image loading/export follows the organization family’s policy.
series[].fieldRequired numeric value source field. Missing/undefined/null produces a null observation; all other values must be finite numbers.
series[].idStable series ID; defaults to its field name. Use these IDs in bindings and overrides.
series[].labelLiteral display label; defaults to its field name.

Category IDs are generated from typed source keys, rather than display labels or array positions. A new mapping must accompany new data in an update. An invalid replacement does not replace the last accepted mapping or row set.