ECharts Plugin System#
Apache Superset implements each ECharts chart type as a self-contained plugin in the plugin-chart-echarts package (~25 chart types). Every plugin follows the same structure, inherits from the ChartPlugin base class in @superset-ui/core, and is assembled into the Superset runtime by a single MainPreset class loaded at application startup.
Key source files:
plugin-chart-echarts/src/index.ts— package public API; exports all plugin classes andtransformPropsfunctionssrc/visualizations/presets/MainPreset.js— the single place where every Superset chart type is registeredpackages/superset-ui-core/src/chart/models/ChartPlugin.ts— baseChartPluginclasspackages/superset-ui-core/src/models/Preset.ts—Presetregistration container
Plugin Anatomy#
Each chart type lives in its own subdirectory under plugin-chart-echarts/src/ and contains the same set of files. The Pie chart is the canonical reference:
| File | Purpose |
|---|---|
index.ts | Plugin class definition; wires together all other files |
controlPanel.tsx | Declarative UI controls for the chart editor |
buildQuery.ts | Constructs the QueryContext sent to the backend |
transformProps.ts | Converts query results + form data into ECharts options |
Echart<Name>.tsx | React component; passes transformed props to the shared <Echart> wrapper |
types.ts | TypeScript types for this chart's form data and props |
constants.ts | Chart-specific constants and defaults |
The plugin class in index.ts extends EchartsChartPlugin , which itself extends the core ChartPlugin . The key difference: EchartsChartPlugin forces parseMethod: 'json-bigint' in the chart metadata to preserve numeric precision for large values.
A typical plugin constructor wires together the five pieces:
super({
buildQuery,
controlPanel,
loadChart: () => import('./EchartsPie'), // lazy-loaded for code splitting
metadata: { behaviors, category, name, thumbnail, ... },
transformProps,
});
transformProps: Query Results → ECharts Options#
transformProps is the most important function in any ECharts plugin. It is typed as TransformProps<Props> — it receives a ChartProps (width, height, form data, raw query data, hooks) and returns an object whose echartOptions field is passed directly to ECharts.
For the Pie chart , the function:
- Extracts form data (color scheme, legend, donut mode, radii, label config) and raw query rows
- Maps database rows to ECharts series data, applying the active color scheme, filter state (opacity), and optional "Other" grouping for small slices
- Assembles the final ECharts config object: tooltip, legend, series, and optional center-label for donut totals
- Returns the config alongside cross-filtering state (
setDataMask,selectedValues,emitCrossFilters) and context-menu handlers
transformProps functions for all charts are re-exported from the package index, making them available for embedding or testing outside the full plugin stack.
Control Panels#
Each plugin's controlPanel.tsx exports a ControlPanelConfig that declares the chart's editor UI. Controls are organized into named sections of rows; each row is an array of control keys or inline control definitions. For example, the Pie control panel has a Query section (groupby, metric, filters, row limit) and a Chart Options section (color scheme, label thresholds, rose type, donut mode, legend).
Controls support:
- Shared controls referenced by string key (e.g.,
'color_scheme','groupby') - Inline custom controls defined directly with
name,config, and optionalvisibilitycallback for conditional display - Shared section helpers (e.g.,
legendSection) imported from the package's shared utilities
The ChartPlugin registers the control panel config into a separate registry during plugin.register() , so the Explore view can dynamically render the correct controls for any chart type.
MainPreset and Plugin Registration#
MainPreset extends the Preset class and is the single place where all Superset chart types are wired into the runtime. It is instantiated and .register() is called at application startup.
The Preset.register() method iterates its plugins and presets arrays and calls plugin.register() on each, which stores the plugin's metadata, component, control panel, transformProps, and buildQuery into five separate singleton registries. The Explore view, chart gallery, and rendering pipeline all read from these registries at runtime.
Notable patterns in MainPreset:
- ECharts plugins are imported from
@superset-ui/plugin-chart-echartsand assigned aVizTypekey via.configure({ key: VizType.Pie }). TheVizTypeenum is the stable identifier used everywhere else (backend, URL params, Explore). - Nested presets are supported:
DeckGLChartPresetis passed in thepresetsarray and registered recursively. - Feature-flag gating:
BigNumberPeriodOverPeriodChartPluginis only added whenFeatureFlag.ChartPluginsExperimentalis enabled . This pattern allows shipping unreleased chart types behind a flag.
Currently, MainPreset registers ~25 ECharts plugins alongside legacy NVD3, DeckGL, and other chart types . The complete ECharts export list is in plugin-chart-echarts/src/index.ts.
Adding a New ECharts Chart Type#
To add a new chart:
- Create a directory under
plugin-chart-echarts/src/<ChartName>/with the standard files (index.ts,controlPanel.tsx,buildQuery.ts,transformProps.ts,Echart<Name>.tsx,types.ts). - Export the plugin class and
transformPropsfromplugin-chart-echarts/src/index.ts. - Register in
MainPreset.jsby importing the plugin class and addingnew Echart<Name>ChartPlugin().configure({ key: VizType.<Name> })to thepluginsarray. - Add the
VizTypeenum value in@superset-ui/coreif it does not already exist.
For experimental charts, conditionally push the plugin into experimentalPlugins behind FeatureFlag.ChartPluginsExperimental before including it in super({...}).