Plugins (Weave)

Weave answers a question ApexCharts got for years: how do I draw my own thing on the chart without forking it or hacking the SVG? A Weave plugin is the supported answer. It registers once by name, activates per chart, subscribes to lifecycle hooks like draw, and paints into its own sandboxed layer. It can read the chart's scales, data, and theme, but it never touches internal state, so it cannot break rendering and it survives version upgrades.

That last part is the point. Because a plugin only ever draws into its own layer and only reads a fixed API, it is safe to publish to npm and drop into any chart. Weave is what makes a real third-party plugin ecosystem for ApexCharts possible.

See it live

The dashed mean line below is not part of the chart config. A plugin computes it on every draw pass: it reads the series, averages the values, converts the mean to a pixel, paints a line and label into its own layer, and emits the value back to the page. Press New data and the plugin recomputes and redraws.

Series with a plugin-drawn mean lineplugin: mean-line

The dashed mean line is not part of the chart config. A Weave plugin computes it on every draw pass and paints it into its own layer.

Where Weave is useful

  • Reference overlays. A mean, median, or target line, control limits for statistical process control, a moving average, an SLA threshold band. The shipped example is the dashed mean-line plugin above, which recomputes on every redraw.
  • Domain overlays. Support and resistance levels or forecast cones in trading, capacity lines in ops dashboards.
  • Branding. A watermark or logo layer applied consistently across every chart in an app.
  • External event markers. Deploy markers, incidents, or release dates pulled from another system and painted on top of a time series.
  • Org-wide reusable behaviors. Publish one plugin to npm so every team's charts get the same overlay or instrumentation by adding a single name to plugins.
  • Analytics instrumentation. Emit namespaced events (a hover, a threshold crossing) for product analytics without modifying chart internals.

Enable the feature

Weave is tree-shakeable. Import the feature once, then register plugins on the ApexCharts class:

import ApexCharts from 'apexcharts'
import 'apexcharts/features/weave'

Register a plugin

ApexCharts.registerPlugin(def) registers a plugin globally, once. Each plugin declares a name, an apiVersion, and a setup(api) function that subscribes to hooks. Call api.layer() inside each draw handler (layers are wiped at the start of every draw pass, so a handle cached across draws points at a detached node):

ApexCharts.registerPlugin({
  name: 'watermark',
  apiVersion: 1,
  setup(api) {
    api.on('draw', () => {
      const layer = api.layer()
      layer.text({ x: 12, y: 22, text: 'ACME', color: '#c8ccd4', size: '12px' })
    })
  },
})

ApexCharts.unregisterPlugin(name) removes it again, which is useful in tests and hot-reload.

Activate a plugin per chart

Registering makes a plugin available; a chart opts in through the plugins array. Registration is global, activation is per chart, so the same plugin can be on some charts and not others. You can pass per-chart options and an order:

const options = {
  plugins: [{ name: 'watermark', options: { text: 'ACME' } }],
}

At runtime, chart.updateOptions({ plugins: [{ name, options }] }) reconfigures an active plugin in place; the new options arrive live as api.options.

The plugin API

setup(api) receives a stable facade, never the chart's internals:

api.on(hook, fn)Subscribe to a lifecycle hook: afterParse, afterScales, draw, afterUpdate, or destroy.
api.layer(opts?)A plugin-owned SVG group with line, path, rect, circle, text, and clear. Pass { z: 'front' } or 'behind' to stack it. Wiped at the start of every draw pass.
api.scalesConvert data values to pixels for the current view: scales.x(v), scales.y(v), plus gridWidth and gridHeight.
api.dataRead-only access to the resolved series (name, color, hidden, points).
api.themeThe resolved theme: mode, foreColor, seriesColor(i), and token(name).
api.storePer-plugin state that survives redraws.
api.emit(name, detail)Send an event back to the page. It fires on the chart's bus as plugin:<name>:<event>.

Two properties of this API are what make plugins safe. First, the layer is sandboxed and cleared before each draw, so a plugin can never corrupt the chart's own output. Second, api.emit is namespaced as plugin:<name>:<event>, so a plugin's events can never trigger the chart's internal lifecycle subscribers. The apiVersion field is a contract the library uses to reject a plugin written against an incompatible API, which is how a plugin keeps working as internals change.

Weave vs Marks

Both are extensibility features, but at different levels:

  • Weave adds overlays and cross-cutting behaviors that are not one-per-datum: reference lines, bands, watermarks, instrumentation. A Weave plugin decorates the whole chart.
  • Marks adds a new data-driven series type: one shape per datum, tied to your data. A Mark defines how a series is drawn.

For a one-off drawing on a single chart, annotations are simpler than either.

Weave ships as a tree-shakeable entry point; see the tree-shaking guide for the full list.