The definitive field-by-field reference for every type in VizSpec. Cross-referenced against the TypeScript source in @opendata-ai/openchart-core/src/types/.
All types are importable from @opendata-ai/openchart-core or from the convenience re-exports in @opendata-ai/openchart-react, @opendata-ai/openchart-vue, @opendata-ai/openchart-svelte, and @opendata-ai/openchart-engine.
- VizSpec (top-level union type)
- ChartSpec (line, area, bar, column, pie, donut, dot, scatter)
- Encoding (x, y, color, size, detail channels)
- Annotations (refline, text, range)
- Labels (density, format, position)
- Chrome (title, subtitle, source, byline, footer)
- ThemeConfig (colors, fonts, spacing)
- DarkMode (auto, force, off)
- TableSpec (data tables with visual features)
- ColumnConfig (column definitions and visual types)
- Event handlers (chart and table interaction callbacks)
- GraphSpec (network/relationship visualizations)
- SankeySpec (flow diagrams)
- Spec builder functions (lineChart, barChart, etc.)
- Validation (validateSpec, error codes)
The top-level type is a discriminated union on the type field:
type VizSpec = ChartSpec | LayerSpec | TableSpec | GraphSpec | SankeySpec;Use type to select which spec shape you're building:
- Chart types (
line,area,bar,column,pie,donut,dot,scatter) produce aChartSpec tableproduces aTableSpecgraphproduces aGraphSpecsankeyproduces aSankeySpec
Type guards are available: isChartSpec(spec), isTableSpec(spec), isGraphSpec(spec), isSankeySpec(spec).
The primary input for standard chart types. Source: core/src/types/spec.ts.
| Field | Type | Default | Description |
|---|---|---|---|
type |
ChartType |
(required) | Chart type: 'line', 'area', 'bar', 'column', 'pie', 'donut', 'dot', 'scatter' |
data |
DataRow[] |
(required) | Array of data rows. Each row is a Record<string, unknown>. Must be non-empty. |
encoding |
Encoding |
(required) | Maps data fields to visual channels. See Encoding. |
chrome |
Chrome |
undefined |
Editorial text: title, subtitle, source, byline, footer. See Chrome. |
annotations |
Annotation[] |
undefined |
Text callouts, highlighted ranges, reference lines. See Annotations. |
labels |
LabelConfig |
undefined |
Data label display controls. See Labels. |
responsive |
boolean |
true |
Whether the chart adapts to container width via ResizeObserver. |
theme |
ThemeConfig |
undefined |
Theme overrides. Deep-merged onto the default theme. See ThemeConfig. |
darkMode |
DarkMode |
'off' |
Dark mode behavior. See DarkMode. |
watermark |
boolean |
true |
Whether to show the tryOpenData.ai watermark. Spec-level value takes precedence over mount/compile options; if neither is set, defaults to true. |
type DataRow = Record<string, unknown>;A plain object with string keys. Values can be numbers, strings, dates, nulls, arrays (for sparklines), or booleans. The engine inspects values at runtime to validate encoding types.
Maps data fields to visual channels. Source: core/src/types/spec.ts.
interface Encoding {
x?: EncodingChannel;
y?: EncodingChannel;
color?: EncodingChannel;
size?: EncodingChannel;
detail?: EncodingChannel;
}Which channels are required depends on the chart type. See Encoding by chart type.
| Field | Type | Default | Description |
|---|---|---|---|
field |
string |
(required) | Data field name. Must match a key in the data rows. |
type |
FieldType |
(required) | How to interpret values: 'quantitative', 'temporal', 'nominal', 'ordinal'. |
aggregate |
AggregateOp |
undefined |
Aggregate applied before encoding: 'count', 'sum', 'mean', 'median', 'min', 'max'. |
axis |
AxisConfig |
undefined |
Axis configuration. Only relevant for x and y channels. |
scale |
ScaleConfig |
undefined |
Scale configuration (domain, type, nice, zero). |
| Value | Meaning | Scale created |
|---|---|---|
quantitative |
Continuous numbers | Linear (or log) |
temporal |
Dates and times | Time |
nominal |
Unordered categories | Band/ordinal |
ordinal |
Ordered categories | Band/ordinal |
'count' | 'sum' | 'mean' | 'median' | 'min' | 'max'
Applied to the field values before encoding. Useful when your data has multiple rows per category and you want a single value per mark.
| Field | Type | Default | Description |
|---|---|---|---|
label |
string |
field name | Axis label text displayed along the axis. |
format |
string |
auto | d3-format string for tick labels, e.g. ",.0f" for comma-separated integers. |
tickCount |
number |
auto | Override the number of ticks. Engine picks a sensible default if omitted. |
grid |
boolean |
true for y-axis |
Whether to show gridlines for this axis. |
| Field | Type | Default | Description |
|---|---|---|---|
domain |
[number, number] or string[] |
auto from data | Explicit domain override. |
type |
'linear' | 'log' | 'time' | 'band' | 'point' | 'ordinal' |
inferred from FieldType | Scale type override. |
nice |
boolean |
true |
Round domain to clean tick values. |
zero |
boolean |
true (quantitative) |
Whether the domain should include zero. |
The engine validates encoding channels at runtime using CHART_ENCODING_RULES. Source: core/src/types/encoding.ts.
Legend: (req) = required, (opt) = optional, -- = not applicable
| Chart Type | x | y | color | size | detail | Notes |
|---|---|---|---|---|---|---|
line |
temporal, ordinal (req) | quantitative (req) | nominal, ordinal (opt) | quantitative (opt) | nominal (opt) | color splits into multi-series with auto legend |
area |
temporal, ordinal (req) | quantitative (req) | nominal, ordinal (opt) | quantitative (opt) | nominal (opt) | Same encoding as line, filled region |
bar |
quantitative (req) | nominal, ordinal (req) | nominal, ordinal (opt) | quantitative (opt) | nominal (opt) | Horizontal bars. x = values, y = categories |
column |
nominal, ordinal, temporal (req) | quantitative (req) | nominal, ordinal (opt) | quantitative (opt) | nominal (opt) | Vertical bars. x = categories, y = values |
pie |
-- (opt, unused) | quantitative (req) | nominal, ordinal (req) | quantitative (opt) | nominal (opt) | color = slice categories, y = slice values |
donut |
-- (opt, unused) | quantitative (req) | nominal, ordinal (req) | quantitative (opt) | nominal (opt) | Same as pie with inner radius |
dot |
quantitative (req) | nominal, ordinal (req) | nominal, ordinal (opt) | quantitative (opt) | nominal (opt) | Dot plot. x = values, y = categories |
scatter |
quantitative (req) | quantitative (req) | nominal, ordinal (opt) | quantitative (opt) | nominal (opt) | Both axes quantitative. size creates bubble chart |
x channel: Horizontal position. Temporal/ordinal for time series (line, area), nominal/ordinal for categories (bar, column), quantitative for values (bar, dot, scatter).
y channel: Vertical position. Quantitative values for most types. Nominal/ordinal categories for bar and dot (horizontal layout).
color channel: Series differentiation. Assigns colors from the categorical palette. Required for pie/donut (defines slices). Optional for all others (creates multi-series with legend).
size channel: Mark size. Creates bubble charts when applied to scatter. Maps a quantitative field to the mark radius or area.
detail channel: Grouping without visual encoding. Splits data into groups (like color does) but doesn't assign different colors. Useful when you want separate lines per group but all the same color.
Editorial text elements. Source: core/src/types/spec.ts.
interface Chrome {
title?: string | ChromeText;
subtitle?: string | ChromeText;
source?: string | ChromeText;
byline?: string | ChromeText;
footer?: string | ChromeText;
}Each field accepts either a plain string or a ChromeText object for style overrides.
| Field | Position | Default style |
|---|---|---|
title |
Top, above chart | 22px, bold (700), #333333 |
subtitle |
Below title | 15px, normal (400), #666666 |
source |
Below chart area | 12px, normal (400), #999999 |
byline |
Below source | 12px, normal (400), #999999 |
footer |
Below byline | 12px, normal (400), #999999 |
When you need to override the default chrome styling:
interface ChromeText {
text: string;
style?: ChromeTextStyle;
}
interface ChromeTextStyle {
fontSize?: number; // Pixels
fontWeight?: number; // 400 = normal, 600 = semibold, 700 = bold
fontFamily?: string; // CSS font family
color?: string; // CSS color string
}Example:
chrome: {
title: { text: 'Revenue by quarter', style: { fontSize: 28, fontWeight: 700 } },
subtitle: 'FY2024 results',
source: 'Source: Internal reporting',
}Only the style properties you provide are overridden. Omitted properties use the theme defaults.
Data-positioned overlays. Source: core/src/types/spec.ts.
Three annotation types are available, discriminated by the type field:
A callout label positioned at a data coordinate.
| Field | Type | Default | Description |
|---|---|---|---|
type |
'text' |
(required) | Discriminant. |
x |
string | number |
(required) | X-axis data value or position. |
y |
string | number |
(required) | Y-axis data value or position. |
text |
string |
(required) | The annotation text. |
label |
string |
undefined |
Additional label text. |
fontSize |
number |
theme default | Font size override in pixels. |
fontWeight |
number |
theme default | Font weight override. |
offset |
AnnotationOffset |
undefined |
Pixel offset from computed position. { dx?: number, dy?: number }. |
anchor |
AnnotationAnchor |
'auto' |
Label placement direction: 'top', 'bottom', 'left', 'right', 'auto'. |
connector |
boolean | 'curve' |
true |
true draws a straight connector line, 'curve' draws a curved arrow with arrowhead, false disables the connector. |
background |
string |
undefined |
Background color behind the text. Renders a masking rect for readability over chart lines. |
fill |
string |
theme annotationFill |
Fill color. |
stroke |
string |
theme annotationText |
Stroke color. |
opacity |
number |
1 |
Opacity (0 to 1). |
zIndex |
number |
0 |
Render ordering. Higher values render on top. |
The text field supports \n for multi-line annotations. Each line renders as a separate <tspan> element, auto-centered within the label.
A highlighted band or rectangle.
| Field | Type | Default | Description |
|---|---|---|---|
type |
'range' |
(required) | Discriminant. |
x1 |
string | number |
undefined |
Start of the range on x-axis. |
x2 |
string | number |
undefined |
End of the range on x-axis. |
y1 |
string | number |
undefined |
Start of the range on y-axis. |
y2 |
string | number |
undefined |
End of the range on y-axis. |
label |
string |
undefined |
Range label text. |
labelOffset |
AnnotationOffset |
undefined |
Pixel offset for the label. { dx?: number, dy?: number }. |
labelAnchor |
AnnotationAnchor |
'auto' |
Label placement direction. |
fill |
string |
theme annotationFill |
Fill color. |
stroke |
string |
undefined |
Stroke color. |
opacity |
number |
1 |
Opacity (0 to 1). |
zIndex |
number |
0 |
Render ordering. |
Range behavior depends on which bounds are provided:
x1/x2only: vertical band (full chart height)y1/y2only: horizontal band (full chart width)- All four: rectangle
A horizontal or vertical reference line.
| Field | Type | Default | Description |
|---|---|---|---|
type |
'refline' |
(required) | Discriminant. |
x |
string | number |
undefined |
X-axis value for a vertical line. |
y |
string | number |
undefined |
Y-axis value for a horizontal line. |
label |
string |
undefined |
Line label text. |
style |
'solid' | 'dashed' | 'dotted' |
'solid' |
Line style. |
strokeWidth |
number |
1 |
Line width in pixels. |
labelOffset |
AnnotationOffset |
undefined |
Pixel offset for the label. |
labelAnchor |
AnnotationAnchor |
'auto' |
Label placement direction. |
fill |
string |
undefined |
Fill color. |
stroke |
string |
theme annotationText |
Stroke/line color. |
opacity |
number |
1 |
Opacity (0 to 1). |
zIndex |
number |
0 |
Render ordering. |
Provide x for a vertical line or y for a horizontal line. Both can be set for a crosshair.
annotations: [
// Horizontal threshold line
{ type: "refline", y: 100, label: "Target", style: "dashed", stroke: "#e45" },
// Highlighted time range
{
type: "range",
x1: "2023-06-01",
x2: "2023-09-01",
label: "Q3",
opacity: 0.08,
},
// Text callout with fine-tuned positioning
{
type: "text",
x: "2023-07-15",
y: 142,
text: "All-time high",
anchor: "top",
offset: { dy: -8 },
connector: true,
},
];Data label display configuration. Source: core/src/types/spec.ts.
interface LabelConfig {
density?: LabelDensity;
format?: string;
}| Field | Type | Default | Description |
|---|---|---|---|
density |
LabelDensity |
'auto' |
How many data labels to show. |
format |
string |
auto | d3-format override for label values, e.g. ",.0f". |
| Value | Behavior |
|---|---|
'all' |
Show every label. No collision detection. Can overlap. |
'auto' |
Show labels with collision detection. Overlapping labels are hidden and only appear in tooltips. |
'endpoints' |
Show only the first and last label per series. Good for line charts where the trend matters more than individual values. |
'none' |
Hide all labels. Rely on tooltips and the legend for value readout. |
User-facing theme overrides. Source: core/src/types/spec.ts.
All fields are optional. The engine deep-merges these onto DEFAULT_THEME. You only specify what you want to change.
interface ThemeConfig {
colors?: {
categorical?: string[];
sequential?: Record<string, string[]>;
diverging?: Record<string, string[]>;
background?: string;
text?: string;
gridline?: string;
axis?: string;
};
fonts?: {
family?: string;
mono?: string;
};
spacing?: {
padding?: number;
chromeGap?: number;
};
borderRadius?: number;
}| Field | Type | Default | Description |
|---|---|---|---|
colors.categorical |
string[] |
8-color palette | Categorical palette for nominal data. Array of CSS color strings. |
colors.sequential |
Record<string, string[]> |
{ blue, green, orange, purple } |
Sequential palettes keyed by name. |
colors.diverging |
Record<string, string[]> |
{ redBlue, brownTeal } |
Diverging palettes keyed by name. |
colors.background |
string |
'#ffffff' |
Visualization background color. |
colors.text |
string |
'#1d1d1d' |
Default text color. |
colors.gridline |
string |
'#e8e8e8' |
Gridline color. |
colors.axis |
string |
'#888888' |
Axis line and tick color. |
| Field | Type | Default | Description |
|---|---|---|---|
fonts.family |
string |
'Inter, -apple-system, ..., sans-serif' |
Primary font family. |
fonts.mono |
string |
'"JetBrains Mono", ..., monospace' |
Monospace font for tabular numbers. |
| Field | Type | Default | Description |
|---|---|---|---|
spacing.padding |
number |
12 |
Padding inside the chart container (px). |
spacing.chromeGap |
number |
4 |
Gap between chrome elements (px). |
| Field | Type | Default | Description |
|---|---|---|---|
borderRadius |
number |
4 |
Border radius for the chart container and tooltips (px). |
The full default theme (from core/src/theme/defaults.ts):
| Property | Value |
|---|---|
colors.background |
#ffffff |
colors.text |
#1d1d1d |
colors.gridline |
#e8e8e8 |
colors.axis |
#888888 |
colors.annotationFill |
rgba(0,0,0,0.04) |
colors.annotationText |
#555555 |
fonts.family |
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif |
fonts.mono |
"JetBrains Mono", "Fira Code", "Cascadia Code", monospace |
fonts.sizes.title |
22 |
fonts.sizes.subtitle |
15 |
fonts.sizes.body |
13 |
fonts.sizes.small |
11 |
fonts.sizes.axisTick |
11 |
fonts.weights.normal |
400 |
fonts.weights.medium |
500 |
fonts.weights.semibold |
600 |
fonts.weights.bold |
700 |
spacing.padding |
12 |
spacing.chromeGap |
4 |
spacing.chromeToChart |
8 |
spacing.chartToFooter |
8 |
spacing.axisMargin |
6 |
borderRadius |
4 |
chrome.title |
22px, 700 weight, #333333, 1.3 line-height |
chrome.subtitle |
15px, 400 weight, #666666, 1.4 line-height |
chrome.source |
12px, 400 weight, #999999, 1.3 line-height |
chrome.byline |
12px, 400 weight, #999999, 1.3 line-height |
chrome.footer |
12px, 400 weight, #999999, 1.3 line-height |
Controls dark mode rendering. Source: core/src/types/spec.ts.
type DarkMode = "auto" | "force" | "off";| Value | Behavior |
|---|---|
'auto' |
Checks window.matchMedia('(prefers-color-scheme: dark)'). Adapts to system preference. |
'force' |
Always render in dark mode. |
'off' |
Always render in light mode. This is the default. |
Dark mode resolution happens in the adapter layer (vanilla/React), not the engine. The adapter resolves the DarkMode union to a boolean and passes darkMode: true/false to the engine's CompileOptions. The engine then calls adaptTheme() to transform colors: swap background/text, adjust palette brightness, lighten gridlines.
You don't need to define a separate dark theme. The engine handles the color transformations automatically.
Input for data table visualizations. Source: core/src/types/spec.ts.
| Field | Type | Default | Description |
|---|---|---|---|
type |
'table' |
(required) | Discriminant. Always 'table'. |
data |
DataRow[] |
(required) | Array of data rows. Must be non-empty. |
columns |
ColumnConfig[] |
(required) | Column definitions. See ColumnConfig. |
rowKey |
string |
auto-generated | Field to use as a unique row identifier. |
chrome |
Chrome |
undefined |
Editorial text (title, subtitle, source, etc.). |
theme |
ThemeConfig |
undefined |
Theme overrides. |
darkMode |
DarkMode |
'off' |
Dark mode behavior. |
search |
boolean |
false |
Enable client-side search/filter bar. |
pagination |
boolean | { pageSize: number } |
false |
Enable pagination. true uses default page size. Object sets explicit page size. |
stickyFirstColumn |
boolean |
false |
Freeze the first column during horizontal scroll. |
compact |
boolean |
false |
Reduced padding and font sizes. |
responsive |
boolean |
true |
Whether the table adapts to container width. |
watermark |
boolean |
true |
Whether to show the tryOpenData.ai watermark. Spec-level value takes precedence over mount/compile options. |
Configuration for a single table column. Source: core/src/types/table.ts.
| Field | Type | Default | Description |
|---|---|---|---|
key |
string |
(required) | Data field key. Must match a key in the data rows. |
label |
string |
same as key |
Display label for the column header. |
sortable |
boolean |
true |
Whether this column is sortable. |
align |
'left' | 'center' | 'right' |
'right' for numbers, 'left' otherwise |
Text alignment. |
width |
string |
auto-sized | CSS width like '200px' or '20%'. |
format |
string |
none | d3-format or d3-time-format string. e.g. ',.0f' for numbers, '%Y-%m-%d' for dates. |
Each column can have at most one visual feature. If multiple are set, precedence is: sparkline > bar > heatmap > image > flag > categoryColors.
| Feature | Config field | Config type | Description |
|---|---|---|---|
| Heatmap | heatmap |
HeatmapColumnConfig |
Color cell background based on numeric value. |
| Inline bar | bar |
BarColumnConfig |
Proportional bar in the cell. |
| Sparkline | sparkline |
SparklineColumnConfig |
Mini line/bar chart from array data. |
| Image | image |
ImageColumnConfig |
Render cell value as an image. |
| Flag | flag |
boolean |
Render cell value as a country flag. |
| Category colors | categoryColors |
Record<string, string> |
Color-code cells by categorical value. |
| Field | Type | Default | Description |
|---|---|---|---|
palette |
string | string[] |
theme sequential | Palette name (e.g. 'blue', 'redBlue') or array of color stops. |
domain |
[number, number] |
auto from data | Explicit min/max for the color scale. |
colorByField |
string |
same column | Use a different field's values for coloring while displaying this column's values. |
| Field | Type | Default | Description |
|---|---|---|---|
maxValue |
number |
auto from data | Maximum value for the bar scale. |
color |
string |
first categorical color | Bar fill color. |
| Field | Type | Default | Description |
|---|---|---|---|
type |
'line' | 'bar' | 'column' |
'line' |
Sparkline chart type. |
valuesField |
string |
same column | Field containing the array of values to plot. |
color |
string |
first categorical color | Sparkline color. |
| Field | Type | Default | Description |
|---|---|---|---|
width |
number |
24 |
Image width in pixels. |
height |
number |
24 |
Image height in pixels. |
rounded |
boolean |
false |
Apply border-radius for circular images. |
type CategoryColorsConfig = Record<string, string>;Maps category string values to CSS color strings. Cells with matching values get the assigned color as background.
categoryColors: {
'Active': '#2a9d8f',
'Inactive': '#e76f51',
'Pending': '#f4a261',
}Interaction callbacks. Source: core/src/types/events.ts.
Pass these through MountOptions (vanilla) or ChartProps (React).
| Handler | Signature | When it fires |
|---|---|---|
onMarkClick |
(event: MarkEvent) => void |
User clicks a data mark (bar, point, line, arc). |
onMarkHover |
(event: MarkEvent) => void |
Mouse enters a data mark. |
onMarkLeave |
() => void |
Mouse leaves a data mark. |
onLegendToggle |
(series: string, visible: boolean) => void |
User clicks a legend entry to show/hide a series. |
onAnnotationClick |
(annotation: Annotation, event: MouseEvent) => void |
User clicks an annotation element. |
| Field | Type | Description |
|---|---|---|
datum |
DataRow |
The data row associated with the mark. For line/area marks, this is the first row of the series. |
series |
string | undefined |
Series identifier for multi-series charts. Matches the color encoding field value. |
position |
{ x: number, y: number } |
Click/hover position relative to the chart container. |
event |
MouseEvent |
The raw browser MouseEvent. |
Table events are passed through TableMountOptions (vanilla) or DataTableProps (React).
| Handler | Signature | When it fires |
|---|---|---|
onRowClick |
(row: Record<string, unknown>) => void |
User clicks a table row. |
onSortChange |
(sort: SortState | null) => void |
Sort state changes (React DataTable only). |
onSearchChange |
(query: string) => void |
Search query changes (React DataTable only). |
onPageChange |
(page: number) => void |
Page changes (React DataTable only). |
onStateChange |
(state: TableState) => void |
Any table state changes (vanilla createTable only). |
Input for network/relationship visualizations. Source: core/src/types/spec.ts.
Graphs render force-directed network visualizations on canvas. They support node interaction (click, drag, double-click), search, zoom/pan, keyboard navigation, and selection. Nodes are positioned by a force simulation running in a web worker.
| Field | Type | Default | Description |
|---|---|---|---|
type |
'graph' |
(required) | Discriminant. |
nodes |
GraphNode[] |
(required) | Node array. Each node must have an id: string field plus arbitrary data fields. |
edges |
GraphEdge[] |
(required) | Edge array. Each edge has source: string and target: string referencing node ids. |
encoding |
GraphEncoding |
undefined |
Visual property mappings for nodes/edges. |
layout |
GraphLayoutConfig |
undefined |
Layout algorithm configuration. |
nodeOverrides |
Record<string, NodeOverride> |
undefined |
Per-node visual overrides keyed by node id. See NodeOverride. |
chrome |
Chrome |
undefined |
Editorial text. |
annotations |
Annotation[] |
undefined |
Annotations. |
theme |
ThemeConfig |
undefined |
Theme overrides. |
darkMode |
DarkMode |
'off' |
Dark mode behavior. |
watermark |
boolean |
true |
Whether to show the tryOpenData.ai watermark. Spec-level value takes precedence over mount/compile options. |
Each channel is a GraphEncodingChannel with field, optional type, and optional scale (same ScaleConfig as chart encodings). When scale.domain and scale.range are provided, the engine uses them directly instead of auto-deriving from the data. This is useful for controlling deterministic color assignment.
| Channel | Field type constraint | Purpose |
|---|---|---|
nodeColor |
nominal, ordinal, quantitative | Color mapping for nodes. |
nodeSize |
quantitative | Size mapping for nodes (3-12px radius). |
edgeColor |
nominal, ordinal, quantitative | Color mapping for edges. |
edgeWidth |
quantitative | Width mapping for edges (0.5-4px). |
edgeStyle |
nominal, ordinal | Line style mapping (solid/dashed/dotted). |
nodeLabel |
any | Label field for nodes. |
When nodeColor encoding is set, it takes precedence over community-based coloring from layout.clustering. Community assignment still affects spatial grouping, but colors are driven by the encoding.
Per-node visual overrides. Useful for highlighting seed nodes, selected nodes, or applying custom styling to specific nodes.
| Field | Type | Description |
|---|---|---|
fill |
string |
Override fill color. |
radius |
number |
Override node radius. |
strokeWidth |
number |
Override stroke width. |
stroke |
string |
Override stroke color. |
alwaysShowLabel |
boolean |
Force label to always show regardless of zoom/priority. |
| Field | Type | Default | Description |
|---|---|---|---|
type |
'force' | 'radial' | 'hierarchical' |
(required) | Layout algorithm. |
clustering |
{ field: string } |
undefined |
Group nodes by a field for cluster forces. |
chargeStrength |
number |
library default | Charge strength for force layout. Negative = repulsion. |
linkDistance |
number |
library default | Target distance between linked nodes. |
collisionPadding |
number |
2 |
Extra pixels added to node radius for collision detection. |
linkStrength |
number |
undefined |
Link force strength override. |
centerForce |
boolean |
true |
Whether to apply center force to keep graph centered. |
Input for flow/Sankey diagram visualizations. Source: core/src/types/spec.ts.
Sankey diagrams show flows between stages. Each data row represents a link from a source node to a target node with a quantitative value. Nodes are auto-derived from the data. Uses a separate component: <Sankey> (React/Vue/Svelte) or createSankey (vanilla).
| Field | Type | Default | Description |
|---|---|---|---|
type |
'sankey' |
(required) | Discriminant. Always 'sankey'. |
data |
DataRow[] |
(required) | Tabular flow data. Each row is a source-target-value link. |
encoding |
SankeyEncoding |
(required) | Maps data fields to source, target, value channels. See below. |
nodeWidth |
number |
12 |
Width of node rectangles in pixels. |
nodePadding |
number |
16 |
Vertical padding between nodes in pixels. |
nodeAlign |
SankeyNodeAlign |
'justify' |
Node alignment: 'left', 'right', 'center', 'justify'. |
iterations |
number |
6 |
Number of layout relaxation iterations. |
linkStyle |
SankeyLinkColor |
'gradient' |
Link coloring: 'gradient', 'source', 'target', 'neutral'. |
linkOpacity |
number |
0.5 |
Link fill opacity (0-1). Defaults to 0.75 in dark mode. |
nodeLabelAlign |
string |
'auto' |
Label placement: 'auto', 'left', 'right'. |
valueFormat |
string |
undefined |
d3-format string for values in tooltips and ARIA labels (e.g. "$,.0f", "~s"). |
chrome |
Chrome |
undefined |
Editorial text (title, subtitle, source, byline, footer). |
legend |
LegendConfig |
undefined |
Legend display configuration. |
theme |
ThemeConfig |
undefined |
Theme overrides. |
darkMode |
DarkMode |
'off' |
Dark mode behavior. |
watermark |
boolean |
true |
Whether to show the tryOpenData.ai watermark. |
animation |
AnimationSpec |
undefined |
Entrance animation configuration. |
| Channel | Type | Required | Description |
|---|---|---|---|
source |
EncodingChannel |
yes | Source node field (nominal). |
target |
EncodingChannel |
yes | Target node field (nominal). |
value |
EncodingChannel |
yes | Flow value field (quantitative). |
color |
EncodingChannel |
no | Color encoding for nodes/links. |
tooltip |
EncodingChannel | EncodingChannel[] |
no | Tooltip encoding. |
import { Sankey } from "@opendata-ai/openchart-react";
const spec: SankeySpec = {
type: "sankey",
data: [
{ source: "Coal", target: "Electricity", value: 46.5 },
{ source: "Natural Gas", target: "Electricity", value: 38.2 },
{ source: "Natural Gas", target: "Heating", value: 25.8 },
{ source: "Electricity", target: "Residential", value: 38.5 },
{ source: "Electricity", target: "Commercial", value: 35.8 },
{ source: "Heating", target: "Residential", value: 15.2 },
],
encoding: {
source: { field: "source", type: "nominal" },
target: { field: "target", type: "nominal" },
value: { field: "value", type: "quantitative" },
},
chrome: {
title: "US Energy Flow",
subtitle: "From primary sources to end-use sectors, quadrillion BTU",
source: "U.S. Energy Information Administration",
},
};const spec: ChartSpec = {
mark: "line",
data: [
{ date: "2023-01-01", revenue: 42000, region: "North" },
{ date: "2023-04-01", revenue: 58000, region: "North" },
{ date: "2023-07-01", revenue: 63000, region: "North" },
{ date: "2023-01-01", revenue: 31000, region: "South" },
{ date: "2023-04-01", revenue: 44000, region: "South" },
{ date: "2023-07-01", revenue: 52000, region: "South" },
],
encoding: {
x: { field: "date", type: "temporal" },
y: {
field: "revenue",
type: "quantitative",
axis: { label: "Revenue ($)", format: ",.0f" },
},
color: { field: "region", type: "nominal" },
},
chrome: {
title: "Revenue by region",
subtitle: "Quarterly results, 2023",
source: "Source: Finance team",
},
labels: { density: "endpoints" },
annotations: [
{ type: "refline", y: 50000, label: "Target", style: "dashed" },
],
};const spec: ChartSpec = {
mark: "area",
data: [
{ month: "2024-01", users: 1200 },
{ month: "2024-02", users: 1800 },
{ month: "2024-03", users: 2400 },
{ month: "2024-04", users: 3100 },
],
encoding: {
x: { field: "month", type: "temporal" },
y: { field: "users", type: "quantitative" },
},
chrome: { title: "User growth" },
};const spec: ChartSpec = {
mark: "bar",
data: [
{ language: "Python", popularity: 29 },
{ language: "JavaScript", popularity: 24 },
{ language: "TypeScript", popularity: 17 },
{ language: "Java", popularity: 14 },
{ language: "Go", popularity: 10 },
],
encoding: {
x: { field: "popularity", type: "quantitative" },
y: { field: "language", type: "nominal" },
},
chrome: { title: "Language popularity" },
};const spec: ChartSpec = {
mark: "bar",
data: [
{ month: "Jan", sales: 120 },
{ month: "Feb", sales: 180 },
{ month: "Mar", sales: 240 },
{ month: "Apr", sales: 210 },
],
encoding: {
x: { field: "month", type: "nominal" },
y: { field: "sales", type: "quantitative" },
},
chrome: { title: "Monthly sales" },
labels: { density: "all", format: ",.0f" },
};const spec: ChartSpec = {
mark: "arc",
data: [
{ category: "Desktop", share: 58 },
{ category: "Mobile", share: 35 },
{ category: "Tablet", share: 7 },
],
encoding: {
y: { field: "share", type: "quantitative" },
color: { field: "category", type: "nominal" },
},
chrome: { title: "Traffic by device" },
};const spec: ChartSpec = {
mark: { type: "arc", innerRadius: 40 },
data: [
{ status: "Complete", count: 42 },
{ status: "In Progress", count: 18 },
{ status: "Blocked", count: 5 },
],
encoding: {
y: { field: "count", type: "quantitative" },
color: { field: "status", type: "nominal" },
},
chrome: { title: "Task status" },
};const spec: ChartSpec = {
mark: "point",
data: [
{ gdp: 21400, lifeExp: 78.9, country: "USA", pop: 331 },
{ gdp: 40300, lifeExp: 83.4, country: "Switzerland", pop: 8.6 },
{ gdp: 1900, lifeExp: 69.4, country: "India", pop: 1380 },
{ gdp: 10500, lifeExp: 76.9, country: "China", pop: 1400 },
],
encoding: {
x: {
field: "gdp",
type: "quantitative",
axis: { label: "GDP per capita ($)" },
},
y: {
field: "lifeExp",
type: "quantitative",
axis: { label: "Life expectancy" },
},
size: { field: "pop", type: "quantitative" },
color: { field: "country", type: "nominal" },
},
chrome: { title: "GDP vs life expectancy" },
};const spec: ChartSpec = {
mark: "circle",
data: [
{ team: "Engineering", satisfaction: 8.2 },
{ team: "Design", satisfaction: 7.9 },
{ team: "Sales", satisfaction: 6.5 },
{ team: "Support", satisfaction: 7.1 },
],
encoding: {
x: { field: "satisfaction", type: "quantitative" },
y: { field: "team", type: "nominal" },
},
chrome: { title: "Team satisfaction scores" },
};const spec: TableSpec = {
type: "table",
data: [
{
city: "San Francisco",
temp: 18.2,
pop: 874961,
trend: [15, 16, 17, 18, 19, 18],
},
{
city: "New York",
temp: 12.8,
pop: 8336817,
trend: [8, 10, 14, 18, 16, 12],
},
{
city: "Austin",
temp: 20.5,
pop: 978908,
trend: [12, 15, 20, 25, 22, 18],
},
],
columns: [
{ key: "city", label: "City" },
{
key: "temp",
label: "Avg Temp (C)",
format: ".1f",
heatmap: { palette: "redBlue" },
},
{ key: "pop", label: "Population", format: ",.0f", bar: {} },
{
key: "trend",
label: "6-Month Trend",
sparkline: { type: "line", valuesField: "trend" },
},
],
chrome: { title: "City comparison" },
search: true,
pagination: { pageSize: 25 },
stickyFirstColumn: true,
};Helper functions that reduce boilerplate. Source: core/src/helpers/spec-builders.ts.
All builders accept field names as strings (auto-infer type from data) or full EncodingChannel objects (when you need to customize type, aggregate, axis, or scale).
| Builder | Signature | Produces |
|---|---|---|
lineChart |
(data, x, y, options?) |
ChartSpec with mark: 'line' |
areaChart |
(data, x, y, options?) |
ChartSpec with mark: 'area' |
barChart |
(data, category, value, options?) |
ChartSpec with mark: 'bar'. category -> y, value -> x |
columnChart |
(data, x, y, options?) |
ChartSpec with mark: 'bar'. x nominal, y quantitative |
pieChart |
(data, category, value, options?) |
ChartSpec with mark: 'arc'. category -> color, value -> y |
donutChart |
(data, category, value, options?) |
ChartSpec with mark: { type: 'arc', innerRadius: 40 }. category -> color, value -> y |
dotChart |
(data, x, y, options?) |
ChartSpec with mark: 'circle' |
scatterChart |
(data, x, y, options?) |
ChartSpec with mark: 'point' |
dataTable |
(data, options?) |
TableSpec. Auto-generates columns from data keys if none provided. |
| Field | Type | Description |
|---|---|---|
color |
FieldRef |
Color encoding for series differentiation. |
size |
FieldRef |
Size encoding (bubble charts). |
chrome |
Chrome |
Editorial chrome. |
annotations |
Annotation[] |
Annotations. |
responsive |
boolean |
Responsive behavior. |
theme |
ThemeConfig |
Theme overrides. |
darkMode |
DarkMode |
Dark mode behavior. |
watermark |
boolean |
Whether to show the tryOpenData.ai watermark. Spec-level value takes precedence over mount/compile options; defaults to true. |
FieldRef is string | EncodingChannel. When a string is provided, inferFieldType() samples up to 20 data values to determine the encoding type (quantitative, temporal, or nominal).
import { lineChart } from "@opendata-ai/openchart-core";
const spec = lineChart(data, "date", "revenue", {
color: "region",
chrome: { title: "Revenue trend" },
annotations: [{ type: "refline", y: 50000, label: "Target" }],
});The engine validates specs at runtime. Source: engine/src/compiler/validate.ts.
import { validateSpec } from "@opendata-ai/openchart-engine";
const result = validateSpec(spec);
// result.valid: boolean
// result.errors: ValidationError[]
// result.normalized: VizSpec | null| Field | Type | Description |
|---|---|---|
message |
string |
Human-readable error description. |
path |
string | undefined |
Dot-path to the field that failed, e.g. 'encoding.x.field'. |
code |
ValidationErrorCode |
Machine-readable error code. |
suggestion |
string |
Actionable fix suggestion. |
| Code | Meaning |
|---|---|
INVALID_TYPE |
Wrong type (expected object, got array, etc.). |
MISSING_FIELD |
Required field is missing. |
INVALID_VALUE |
Field has an invalid value (bad chart type, bad dark mode string, etc.). |
EMPTY_DATA |
Data array is empty. |
DATA_FIELD_MISSING |
Encoding references a field that doesn't exist in the data. |
ENCODING_MISMATCH |
Encoding type doesn't match the channel requirements or the actual data values. |
- Chart types for a visual gallery with boilerplate specs and live examples
- Tables for data table features (heatmaps, sparklines, flags, and more)
- Graphs for network/relationship visualizations
- Getting started for a hands-on tutorial
- Architecture for how the packages and compilation pipeline work
- Integration guide for building apps on top of the library