# chartist/live (Chartist API)

> Live updates: the renderer that changes a chart’s SVG in place, the keyed diff, and SMIL update animations.

## smilAnimations

*experimental · from `chartist/live`*

```ts
function smilAnimations(): LiveAnimations
```

Animates the changes of an update with SMIL, timed by the chart's CSS: each updated node's changed numbers and paths move from their previous value to their new one over `--ct-update-duration` (a CSS time, 300 ms by default; `0s` turns the animations off) with the easing in `--ct-update-easing` (a CSS easing, `ease-out` by default). The attributes hold their new values from the start, and an update during an animation continues from where each element is drawn.

It animates updates (`update()`, `setOptions()`) and changes of the matching `responsive` options, not resizes, and nothing while the visitor's system asks for reduced motion. Lines and areas follow their values' keys, and pie slices turn around the pie; layers and plugins can give keyframes of their own.

Returns: The animations, for `liveDomRenderer({ animations })`

```ts
import { lineChart } from 'chartist';
import { liveDomRenderer, smilAnimations } from 'chartist/live';

// 300 ms with ease-out, unless the CSS sets --ct-update-duration
// and --ct-update-easing.
const chart = lineChart(
  '#chart',
  { labels: ['Mon', 'Tue', 'Wed'], series: [[5, 2, 4]] },
  { renderer: liveDomRenderer({ animations: smilAnimations() }) }
);

chart.update({ data: { labels: ['Mon', 'Tue', 'Wed'], series: [[3, 6, 1]] } });
```

## diffScenes

*experimental · from `chartist/live`*

```ts
function diffScenes(previous: SceneNode, next: SceneNode, options?: DiffOptions): SceneChange[]
```

The changes between two scenes, matched by what each node stands for: `add`, `update` (with the previous node) and `remove`, in the new scene's document order, with the `remove` entries after their former parent's kept children. Every node of an added or removed subtree has its own entry. The live renderer patches its SVG with them; other renderers that change their output in place can use them too.

Nodes are matched among the children of matched parents: values by their layer, series and key (see `key`), series by layer and index, grid lines and axis labels by axis and tick, nodes with their own `key` by it, and the rest by element name and first class, in order.

Parameters:

- `previous: SceneNode` The previous scene
- `next: SceneNode` The new scene
- `options?: DiffOptions` How values are identified, and the data's labels

Returns: The changes, in the new scene's document order

```ts
import { lineChartConfig, toScene } from 'chartist';
import { diffScenes } from 'chartist/live';

const size = { width: 600, height: 300 };
const labels = ['Mo', 'Tu', 'We'];
const before = toScene(lineChartConfig({ labels, series: [[1, 2, 3]] }), size);
const after = toScene(lineChartConfig({ labels, series: [[1, 5, 3]] }), size);

for (const { op, node } of diffScenes(before, after, { labels })) {
  console.log(op, node.role, node.key);
}
```

## liveDomRenderer

*experimental · from `chartist/live`*

```ts
function liveDomRenderer(options?: LiveDomRendererOptions): Renderer<DomRenderOutput>
```

Creates a DOM renderer that keeps a chart's SVG and changes it in place on every later render, instead of drawing a new one: elements that stand for the same thing as before stay, with only their changed attributes, classes and text set, elements for new nodes are created and elements of nodes that are gone are removed. What listeners added to kept elements stays, and `mount` gets the `changes` of the render.

Its first render, and every render without the previous one (1.x charts), draws a new SVG as [`domRenderer`](https://chartist.dev/api/rendering/#domRenderer) does. A chart whose container holds markup from `renderForHydration()` takes that markup over instead, keeping the server's elements, unless `adopt` is `false`. The renderer keeps no state of its own, so one instance can serve many charts.

Parameters:

- `options?: LiveDomRendererOptions` How values are identified (`key`), update animations,   such as `smilAnimations()`, and whether to take server markup over

Returns: The renderer, for `renderer` in `chart()` and the presets

```ts
import { lineChart } from 'chartist';
import { liveDomRenderer } from 'chartist/live';

const labels = ['Mo', 'Tu', 'We', 'Th', 'Fr'];
const values = [3, 5, 4, 6, 5];
const chart = lineChart(
  '#chart',
  { labels, series: [values] },
  // Points and labels follow their day as the window slides.
  { renderer: liveDomRenderer({ key: 'label' }) }
);

let day = 0;
setInterval(() => {
  labels.push(`Day ${++day}`);
  labels.shift();
  values.push(Math.round(Math.random() * 10));
  values.shift();
  chart.update({ labels: [...labels], series: [[...values]] });
}, 1000);
```

## ValueKeyContext

*experimental · from `chartist/live`*

```ts
interface ValueKeyContext
```

What [`ValueKey`](https://chartist.dev/api/live/#ValueKey) functions get about a value: where it is, the value itself, the label at its position and its meta.

Properties:

- `seriesIndex: number` The series' index in the chart's data.
- `valueIndex: number` The value's index in its series (for pie data, 0).
- `value: unknown` The value, as the layer drew it.
- `label: unknown` The label at the value's position: `labels[valueIndex]`, or the slice's label in pie data.
- `meta: unknown` The value's meta, if any.

## ValueKey

*experimental · from `chartist/live`*

```ts
type ValueKey = 'index' | 'label' | ((value: ValueKeyContext) => string | number)
```

What identifies a value across updates: `'index'` (the default) its position in its series, `'label'` the label at its position, or a function of the value, such as `({ meta }) => meta.id`.

## DiffOptions

*experimental · from `chartist/live`*

```ts
interface DiffOptions
```

The options of [`diffScenes`](https://chartist.dev/api/live/#diffScenes): how values are identified, and the labels for `key: 'label'`.

Properties:

- `key?: ValueKey` What identifies a value across updates; `'index'` by default.
- `labels?: readonly unknown[]` The new scene's labels, for `key: 'label'`.
- `previousLabels?: readonly unknown[]` The previous scene's labels, for `key: 'label'`; `labels` if omitted.

## LiveAnimationContext

*experimental · from `chartist/live`*

```ts
interface LiveAnimationContext
```

What the live renderer hands its [`LiveAnimations`](https://chartist.dev/api/live/#LiveAnimations) after patching the SVG of an update.

Properties:

- `changes: readonly SceneChange[]` The changes the render made, in document order.
- `elementOf: (node: SceneNode) => Element | undefined` The element of a node of the new scene.
- `update: RenderUpdate` The previous render, with the cause and the keyframes lookup.
- `container: Element` The chart's container.
- `scene: SceneNode` The new scene.
- `measureStyle?: MeasureStyle` Reads computed styles in the container, with the chart's root classes.
- `valueKey: (context: Omit<ValueKeyContext, 'label'>, scene: 'previous' | 'next') => string` The key that identifies a value across updates, as the renderer's `key` option says: for the value at `valueIndex` of series `seriesIndex`, with its value and meta, in the previous scene or the new one (labels differ between them).

## LiveAnimations

*experimental · from `chartist/live`*

```ts
interface LiveAnimations
```

Update animations for the live renderer, such as [`smilAnimations`](https://chartist.dev/api/live/#smilAnimations): called after the SVG of an update was patched, it starts the animations and returns their timing, or nothing when the render doesn't animate.

Properties:

- `animate: (context: LiveAnimationContext) => UpdateAnimation | undefined` Starts the update animations of a render.

## LiveDomRendererOptions

*experimental · from `chartist/live`*

```ts
interface LiveDomRendererOptions
```

The options of [`liveDomRenderer`](https://chartist.dev/api/live/#liveDomRenderer).

Properties:

- `key?: ValueKey` What identifies a value across updates; `'index'` by default.
- `animations?: LiveAnimations` Update animations, such as `smilAnimations()`; none by default.
- `adopt?: boolean` Takes over markup from `renderForHydration()` in the chart's container and keeps its elements; `true` by default. With `false`, the chart draws a new svg over the server markup.
