The adapter controller is the low-level lifecycle used by framework bindings. Application code normally uses its framework's chart component or mountChart.
import {
createChartAdapter,
resolveChartAdapterLayout,
type ChartAdapter,
type ChartAdapterLayout,
type ChartAdapterLayoutOptions,
} from '@tanstack/charts/adapter'
import { createChartRendererAdapter } from '@tanstack/charts/adapter/renderer'createChartAdapter accepts the SVG-oriented ChartHostOptions. createChartRendererAdapter accepts ChartRendererHostOptions, including an explicit renderer, so a framework can expose a renderer-neutral binding.
function createChartAdapter<
TDatum,
TXValue extends ChartValue = ChartValue,
TYValue extends ChartValue = ChartValue,
>(
initialOptions: ChartHostOptions<TDatum, TXValue, TYValue>,
): ChartAdapter<
ChartHostOptions<TDatum, TXValue, TYValue>,
TDatum,
TXValue,
TYValue
>function createChartRendererAdapter<
TDatum,
TXValue extends ChartValue = ChartValue,
TYValue extends ChartValue = ChartValue,
>(
initialOptions: ChartRendererHostOptions<TDatum, TXValue, TYValue>,
): ChartAdapter<
ChartRendererHostOptions<TDatum, TXValue, TYValue>,
TDatum,
TXValue,
TYValue
>Both factories preserve the definition's datum and coordinate types from the host options and return the same lifecycle contract:
interface ChartAdapter<
TOptions,
TDatum = unknown,
TXValue extends ChartValue = ChartValue,
TYValue extends ChartValue = ChartValue,
> {
prerender: () => string
mount: (container: HTMLElement) => void
update: (options: TOptions) => void
getScene: () => ChartScene<TDatum, TXValue, TYValue> | undefined
destroy: () => void
}| Method | Contract |
|---|---|
| prerender() | Compiles the current options at the resolved initial size and returns the selected renderer's deterministic markup. |
| mount() | Mounts into one container. Calling it again while mounted throws. A preceding prerender shares the controller's runtime. |
| update() | Replaces the complete options object. Before mount it updates later prerender and mount work; after mount it forwards the update to the live host. |
| getScene() | Returns undefined before mount, including after prerender, and the current compiled scene after mount. |
| destroy() | Releases the mounted host, runtime, observers, renderer surface, and interaction listeners. Repeated calls after cleanup have no effect. |
Keep one controller per framework component instance.
const adapter = createChartAdapter(options)
const initialMarkup = adapter.prerender()
// In the browser lifecycle:
container.innerHTML = initialMarkup
adapter.mount(container)
adapter.update(nextOptions)
adapter.destroy()A server controller and browser controller are separate instances. The browser's initial render and mount should reuse one browser controller. The renderer decides which compatible shell or root it adopts. The SSR and Hydration guide covers framework integration requirements.
interface ChartAdapterLayoutOptions {
width?: number
height?: number
initialWidth?: number
aspectRatio?: number
}
interface ChartAdapterLayout {
aspectRatio?: number
initialWidth: number
initialHeight: number
}
function resolveChartAdapterLayout(
options: ChartAdapterLayoutOptions,
): ChartAdapterLayoutresolveChartAdapterLayout makes server geometry deterministic before browser measurement:
| Result | Resolution |
|---|---|
| initialWidth | width, then initialWidth, then 640 |
| aspectRatio | The supplied value only when it is finite and greater than zero |
| initialHeight | height, then initialWidth / aspectRatio when the ratio is valid, then 320 |
An explicit width therefore overrides initialWidth, and an explicit height overrides ratio-derived height. Framework adapters can also use the validated aspectRatio to keep the container stable until its measured width is available.
The controller owns chart runtime and host cleanup. The framework binding owns component identity, native lifecycle hooks, reactive option assembly, and container presentation. Use the renderer-neutral factory only when the framework entry accepts an application-selected ChartRenderer.