# Events and plugins (Chartist API)

> The pipeline phases, their events and payloads, custom events, and the plugin shape.

## withOptions

*experimental*

```ts
function withOptions<TOptions>(plugin: ChartPlugin<TOptions>, options: TOptions): PluginWithOptions<TOptions>
```

Pairs a plugin with its options for a chart's `plugins`, and checks the options against the plugin's options type. `install` receives them as its second argument.

Parameters:

- `plugin: ChartPlugin<TOptions>`
- `options: TOptions`

```ts
import { lineChart, withOptions, type ChartPlugin } from 'chartist';

const lastPoint: ChartPlugin<{ className: string }> = {
  name: 'last-point',
  install(chart, options) {
    chart.on('compose', current => {
      if (current.role !== 'series') {
        return;
      }
      const last = current.children.at(-1);
      return last && options
        ? current.replace(last, last.addClass(options.className))
        : undefined;
    });
  }
};

lineChart(
  '#chart',
  { series: [[1, 3, 2, 5]] },
  { plugins: [withOptions(lastPoint, { className: 'ct-last' })] }
);
```

## ChartEvents

*experimental*

```ts
interface ChartEvents
```

The custom events a chart can emit, by name, with their payloads. The core emits only `responsive`. A plugin that emits events of its own declares them here (TypeScript merges your declaration into Chartist's), so `on()`, `off()` and `emit()` check the names and payloads:

```ts
declare module 'chartist' {
  interface ChartEvents {
    'legend:click': { readonly seriesIndex: number };
  }
}
```

`chartist/compat` declares the 1.x events (`draw`, `created`, …).

Properties:

- `responsive: { … } | { … }` Responsive entries changed which overrides apply: the config before and after (`chart()`), or the options before and after (presets).
- `data: DataEvent` 1.x: the chart's data, before the first render (`type: 'initial'`) and after an update with new data (`type: 'update'`). Listeners can change it in place. Needs the [`compat`](https://chartist.dev/api/compat/#compat) plugin.
- `optionsChanged: OptionsChangedEvent` 1.x: the responsive options changed, with the options before and after. Needs the [`compat`](https://chartist.dev/api/compat/#compat) plugin.
- `draw: AxesDrawEvent | PointDrawEvent | LineDrawEvent | AreaDrawEvent | BarDrawEvent | SliceDrawEvent | SliceLabelDrawEvent` 1.x: an element was drawn: a grid line, label, point, line, area, bar or slice, with its live `element`. Check `type` to narrow it. Needs the [`compat`](https://chartist.dev/api/compat/#compat) plugin.
- `created: LineChartCreatedEvent | BarChartCreatedEvent | PieChartCreatedEvent` 1.x: the chart is drawn and in the DOM, after its `draw` events, with the `svg`, the chart area and the axes. Needs the [`compat`](https://chartist.dev/api/compat/#compat) plugin.
- `animationBegin: AnimationEvent` 1.x: an SMIL animation began, started with `animate()` on an element of the chart, such as the `element` of a `draw` event. Needs the [`compat`](https://chartist.dev/api/compat/#compat) plugin.
- `animationEnd: AnimationEvent` 1.x: an SMIL animation ended, started with `animate()` on an element of the chart. Needs the [`compat`](https://chartist.dev/api/compat/#compat) plugin.

## CustomEventName

```ts
type CustomEventName = keyof ChartEvents & string
```

The name of a custom event: a key of [`ChartEvents`](https://chartist.dev/api/events-and-plugins/#ChartEvents). Plugins list the names they emit in `provides`.

## ChartPlugin

*experimental*

```ts
interface ChartPlugin<TOptions = unknown>
```

A plugin: a name and an `install` function that registers listeners on the chart. Plugins go into `plugins`, in the config of [`chart`](https://chartist.dev/api/chart/#chart) or the options of the presets. They install in order, so with two listeners on the same event, the earlier plugin's runs first.

For options, write a function that takes them and returns the plugin, or read them from the second argument of `install` and pass the plugin with [`withOptions`](https://chartist.dev/api/events-and-plugins/#withOptions).

Properties:

- `name: string` Names the plugin. Prefix your custom events with it to keep them apart.
- `provides?: readonly CustomEventName[]` The custom events this plugin emits with `chart.emit()`, each declared in [`ChartEvents`](https://chartist.dev/api/events-and-plugins/#ChartEvents). They're known before any plugin installs, so another plugin may listen to them.
- `install: (chart: ChartHandle, options?: TOptions) => void` Sets the plugin up: runs once, before the first render, with the chart's handle. Listeners registered here stay for every later render, after updates and resizes too, and `off(name)` without a listener leaves them alone: remove one with its reference.

```ts
import { barChart, type ChartPlugin } from 'chartist';

// Bars at or above the limit get the class ct-over.
const threshold = (limit: number): ChartPlugin => ({
  name: 'threshold',
  install(chart) {
    chart.on('compose', current => {
      if (current.role !== 'bar') {
        return;
      }
      const { value } = current.ctx;
      const y =
        typeof value === 'number'
          ? value
          : value && 'y' in value
            ? value.y
            : undefined;
      return y !== undefined && y >= limit
        ? current.addClass('ct-over')
        : undefined;
    });
  }
});

barChart('#chart', { series: [[5, 4, 3, 7]] }, { plugins: [threshold(5)] });
```

## PluginWithOptions

```ts
type PluginWithOptions<TOptions = unknown> = readonly [ChartPlugin<TOptions>, TOptions]
```

A plugin paired with its options, as [`withOptions`](https://chartist.dev/api/events-and-plugins/#withOptions) creates it. `install` receives the options as its second argument.

## PluginEntry

```ts
type PluginEntry = ChartPlugin<any> | PluginWithOptions<any>
```

An entry of a chart's `plugins`: a plugin, or a plugin with its options. Prefer [`withOptions`](https://chartist.dev/api/events-and-plugins/#withOptions) (it checks the options) or a function that returns a plugin over a bare `[plugin, options]` pair. A 1.x plugin (a plain function) throws; convert it with `fromLegacyPlugin()` from `chartist/compat`.

## ChartData

```ts
interface ChartData
```

Chart data as passed to `chart()` or `toScene()`.

Properties:

- `labels?: readonly (string | number | Date)[]` The labels of the values, e.g. for the X axis or the slices.
- `series: readonly unknown[]` The series: arrays of values, series objects with `data`, or, for a pie, one value per slice.

## PreparedSeries

```ts
interface PreparedSeries
```

One series after the `prepare` phase.

Properties:

- `name?: string` The series' `name`, from a series object.
- `className?: string` The series' `className`, from a series object.
- `meta?: unknown` The series' `meta`, from a series object.
- `values: readonly unknown[]` The series' values, as given.

## PreparedData

```ts
interface PreparedData
```

The data after the `prepare` phase: every series as a [`PreparedSeries`](https://chartist.dev/api/events-and-plugins/#PreparedSeries), whether it was given as an array or an object.

Properties:

- `labels: readonly (string | number | Date)[]` The labels as given, or an empty array.
- `series: readonly PreparedSeries[]` The series, each with its `values`.
- `flat?: boolean` The input was a flat series (e.g. pie or distributed bar data).

## Area

```ts
interface Area
```

The drawing area inside the padding (and the axes), in px in the SVG. `y1` is the bottom edge, as in 1.x.

Properties:

- `x1: number` The left edge.
- `y1: number` The bottom edge.
- `x2: number` The right edge.
- `y2: number` The top edge.
- `width: number` The area's width in px.
- `height: number` The area's height in px.

## Layout

```ts
interface Layout
```

The payload of the `layout` phase: the chart's size and the drawing area inside its padding and axes. A `layout` listener can return a changed layout, e.g. to make room for a legend.

Properties:

- `width: number` The chart's width in px (at least the left and right padding).
- `height: number` The chart's height in px (at least the top and bottom padding).
- `padding: ChartPadding` The padding around the drawing area, in px.
- `area: Area` Where the layers draw, inside the padding and the axes.

## NormalizedChartData

```ts
interface NormalizedChartData
```

Data normalized for axes: multi values (`{ x, y }`), padded labels.

Properties:

- `labels: readonly Label[]` The labels, padded with empty strings to the longest series.
- `series: readonly NormalizedSeries[]` The series' values as numbers, `{ x, y }` values or holes, each series padded with holes to the longest one.

## ResolvedConfig

```ts
interface ResolvedConfig
```

Options after the `resolve` phase: defaults applied, listeners removed.

Properties:

- `data: ChartData` The chart's data, as given.
- `layers: readonly Layer[]` The layers, drawn in this order.
- `coordinates: Coordinates` The coordinate system; `cartesian` unless the config says otherwise.
- `padding: ChartPadding` The padding in px on every side, the 1.x defaults filled in.
- `axes?: CartesianAxes` The chart's axes, from `cartesianAxes()`, if it has any.
- `width?: string | number` The root svg's `width` from the config, e.g. `100%` or `600`.
- `height?: string | number` The root svg's `height` from the config, e.g. `300px`.
- `viewBox?: { … }` Fixed drawing coordinates for the root svg's `viewBox`, in px.
- `className?: string` Class names of the root svg, e.g. `ct-chart-line`.
- `labels?: LabelMode` Label mode for all label layers; else the renderer decides.
- `preset?: LinePresetState | BarPresetState | PiePresetState` The preset that created the chart, if any: its kind, options and data. Check `kind` to narrow it, e.g. `config.preset?.kind === 'line'`.

## PhaseEvents

```ts
interface PhaseEvents
```

The payloads of the phase events, by phase, in the order the phases run. Listen with `on` in the config of `chart()`, `chart.on()` or a plugin. A listener can return a new payload to change the phase (see [`PhaseResult`](https://chartist.dev/api/events-and-plugins/#PhaseResult)); later phases build on the change.

When the container resizes, the chart runs again from `layout`, so `resolve` and `prepare` listeners aren't called.

Properties:

- `resolve: { … }` The config with defaults applied: padding, coordinates, layers, axes.
- `prepare: { … }` The data, each series as `{ values, name, className, meta }`.
- `layout: Layout` The chart's size and the drawing area inside the padding and axes.
- `compose: SceneNode` Each node with a role that a layer draws, children before their parents: series, lines, areas, points, bars, slices, grid lines and labels. Return a changed node, a new one, or `null` to drop it.
- `scene: { … }` The whole scene, its root the `svg`.
- `render: { … }` The renderer has written the scene; `output` is what it returned.
- `mount: { … }` The rendered SVG is in the page; touch elements only here.

```ts
import { barChart, type ChartPlugin } from 'chartist';

// Bars at or above the limit get the class ct-over.
const threshold = (limit: number): ChartPlugin => ({
  name: 'threshold',
  install(chart) {
    chart.on('compose', current => {
      if (current.role !== 'bar') {
        return;
      }
      // A number, { x, y } (with an X scale axis) or a hole.
      const { value } = current.ctx;
      const y =
        typeof value === 'number'
          ? value
          : value && 'y' in value
            ? value.y
            : undefined;
      return y !== undefined && y >= limit
        ? current.addClass('ct-over')
        : undefined;
    });
  }
});

barChart(
  '#chart',
  { labels: ['Q1', 'Q2', 'Q3', 'Q4'], series: [[5, 4, 3, 7]] },
  { plugins: [threshold(5)] }
);
```

## PhaseName

```ts
type PhaseName = keyof PhaseEvents
```

The name of a pipeline phase, such as `compose`: a key of [`PhaseEvents`](https://chartist.dev/api/events-and-plugins/#PhaseEvents).

## PhaseResult

```ts
type PhaseResult<K extends PhaseName> = K extends 'render' | 'mount' ? void : PhaseEvents[K] | K extends 'compose' ? null : never | undefined | void
```

What a phase listener returns: a new payload to transform the phase, or nothing to keep it. `compose` listeners may return `null` to drop the node. `render` and `mount` listeners return nothing (they observe).

## PhaseListener

```ts
type PhaseListener<K extends PhaseName> = (payload: PhaseEvents[K]) => PhaseResult<K>
```

A listener of one phase: gets the phase's payload and may return a new one (see [`PhaseResult`](https://chartist.dev/api/events-and-plugins/#PhaseResult)). Listeners of a phase run in the order they were added, each with the previous one's result.

## AllPhasesListener

```ts
type AllPhasesListener = (name: PhaseName, payload: unknown) => void
```

A listener of every phase (`'*'`): gets the phase name and its final payload, after the phase's own listeners. It only observes.

## PhaseListeners

```ts
type PhaseListeners = { [K in PhaseName]?: PhaseListener<K> } & { … }
```

Phase listeners by phase name, as the `on` option of `chart()` takes them. They're registered before the first render.

Properties:

- `*?: AllPhasesListener` Listens to every phase, with the phase name as first argument.
