← All @molecule/* packages · App templates

@molecule/app-charts

Feature · charts · App (browser) · v1.0.1 · Apache-2.0

Framework-agnostic chart interface (createChart/createLineChart/… + swappable ChartProvider); built-in provider renders text placeholders only — bond a real provider for production charts

npm install @molecule/app-charts

npm · Source on GitHub

How it works

@molecule/app-charts is a ready-made charts feature for the app (browser) side. It composes the core interfaces it needs, so it works with whichever providers your app has bonded.

import { useEffect, useRef } from 'react'
import { createLineChart } from '@molecule/app-charts'

export function RevenueChart() {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  useEffect(() => {
    if (!canvasRef.current) return
    const chart = createLineChart(canvasRef.current, {
      labels: ['Jan', 'Feb', 'Mar', 'Apr'],
      datasets: [{ label: 'Revenue', data: [4200, 5800, 5100, 7300] }],
    })
    return () => chart.destroy()
  }, [])
  return <canvas ref={canvasRef} width={600} height={300} />
}

Providers (1): @molecule/app-charts-chartjs

Works with: @molecule/app-bond, @molecule/app-i18n

Reference

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Chart interface for molecule.dev.

A framework-agnostic, imperative charting API: createChart(container, config) plus shorthands (createLineChart, createBarChart, createPieChart, createDoughnutChart, createAreaChart, createScatterChart, createRadarChart), color utilities (colorPalettes, getColor, generateColors), and a swappable ChartProvider contract so any chart library (Chart.js, Recharts, D3, uPlot, …) can back the same calls.

Quick Start

import { useEffect, useRef } from 'react'
import { createLineChart } from '@molecule/app-charts'

export function RevenueChart() {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  useEffect(() => {
    if (!canvasRef.current) return
    const chart = createLineChart(canvasRef.current, {
      labels: ['Jan', 'Feb', 'Mar', 'Apr'],
      datasets: [{ label: 'Revenue', data: [4200, 5800, 5100, 7300] }],
    })
    return () => chart.destroy()
  }, [])
  return <canvas ref={canvasRef} width={600} height={300} />
}

Type

feature

Installation

npm install @molecule/app-charts @molecule/app-bond @molecule/app-i18n

API

Interfaces

AnimationConfig

Chart animation settings (duration, easing, delay, loop, disable).

interface AnimationConfig {
  /**
   * Animation duration (ms).
   */
  duration?: number

  /**
   * Easing function.
   */
  easing?:
    | 'linear'
    | 'easeInQuad'
    | 'easeOutQuad'
    | 'easeInOutQuad'
    | 'easeInCubic'
    | 'easeOutCubic'
    | 'easeInOutCubic'
    | 'easeInBounce'
    | 'easeOutBounce'
    | 'easeInOutBounce'

  /**
   * Delay before animation.
   */
  delay?: number

  /**
   * Loop animation.
   */
  loop?: boolean

  /**
   * Disable animations.
   */
  disabled?: boolean
}

AxisConfig

Chart axis settings (type, title, min/max, grid, ticks, stacking, time unit).

interface AxisConfig {
  /**
   * Axis type.
   */
  type?: 'linear' | 'logarithmic' | 'category' | 'time' | 'timeseries'

  /**
   * Axis title.
   */
  title?: {
    display?: boolean
    text?: string
    color?: string
    font?: FontConfig
  }

  /**
   * Min value.
   */
  min?: number

  /**
   * Max value.
   */
  max?: number

  /**
   * Begin at zero.
   */
  beginAtZero?: boolean

  /**
   * Display axis.
   */
  display?: boolean

  /**
   * Grid configuration.
   */
  grid?: {
    display?: boolean
    color?: string
    lineWidth?: number
    drawBorder?: boolean
  }

  /**
   * Ticks configuration.
   */
  ticks?: {
    display?: boolean
    color?: string
    font?: FontConfig
    stepSize?: number
    maxTicksLimit?: number
    callback?: (value: number | string) => string
  }

  /**
   * Stacked axis.
   */
  stacked?: boolean

  /**
   * Position.
   */
  position?: 'top' | 'bottom' | 'left' | 'right'

  /**
   * Time unit (for time axes).
   */
  time?: {
    unit?:
      'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'
    displayFormats?: Record<string, string>
    tooltipFormat?: string
  }
}

ChartConfig

Full chart configuration (type, datasets, labels, axes, legend, tooltip, animation, responsive).

interface ChartConfig {
  /**
   * Chart type.
   */
  type: ChartType

  /**
   * Datasets.
   */
  datasets: Dataset[]

  /**
   * Labels (for category charts).
   */
  labels?: (string | number)[]

  /**
   * Chart title.
   */
  title?: {
    display?: boolean
    text?: string
    color?: string
    font?: FontConfig
    padding?: number
    position?: 'top' | 'bottom'
  }

  /**
   * X-axis configuration.
   */
  xAxis?: AxisConfig

  /**
   * Y-axis configuration.
   */
  yAxis?: AxisConfig

  /**
   * Additional axes (for multi-axis charts).
   */
  axes?: Record<string, AxisConfig>

  /**
   * Legend configuration.
   */
  legend?: LegendConfig

  /**
   * Tooltip configuration.
   */
  tooltip?: TooltipConfig

  /**
   * Animation configuration.
   */
  animation?: AnimationConfig

  /**
   * Responsive.
   */
  responsive?: boolean

  /**
   * Maintain aspect ratio.
   */
  maintainAspectRatio?: boolean

  /**
   * Aspect ratio.
   */
  aspectRatio?: number

  /**
   * Padding.
   */
  padding?: number | { top?: number; right?: number; bottom?: number; left?: number }

  /**
   * Click handler.
   */
  onClick?: (event: unknown, elements: unknown[], chart: unknown) => void

  /**
   * Hover handler.
   */
  onHover?: (event: unknown, elements: unknown[], chart: unknown) => void
}

ChartInstance

Live chart instance with update, resize, destroy, dataset manipulation, and image export.

interface ChartInstance {
  /**
   * Updates the chart with new data/config.
   */
  update(config?: Partial<ChartConfig>): void

  /**
   * Resizes the chart.
   */
  resize(): void

  /**
   * Destroys the chart.
   */
  destroy(): void

  /**
   * Gets the chart as a base64 image.
   */
  toBase64Image(type?: string, quality?: number): string

  /**
   * Gets the underlying chart instance.
   */
  getInstance(): unknown

  /**
   * Shows a dataset.
   */
  showDataset(index: number): void

  /**
   * Hides a dataset.
   */
  hideDataset(index: number): void

  /**
   * Toggles a dataset.
   */
  toggleDataset(index: number): void

  /**
   * Gets visible datasets.
   */
  getVisibleDatasets(): number[]

  /**
   * Sets data for a dataset.
   */
  setData(datasetIndex: number, data: (number | DataPoint)[]): void

  /**
   * Adds a dataset.
   */
  addDataset(dataset: Dataset): void

  /**
   * Removes a dataset.
   */
  removeDataset(index: number): void

  /**
   * Adds data point(s) to all datasets.
   */
  addData(label: string | number, values: number[]): void

  /**
   * Removes data point(s) from all datasets.
   */
  removeData(index?: number): void
}

ChartProvider

Chart provider interface.

interface ChartProvider {
  /**
   * Creates a chart instance.
   */
  createChart(container: HTMLCanvasElement | HTMLElement, config: ChartConfig): ChartInstance

  /**
   * Gets the provider name.
   */
  getName(): string

  /**
   * Gets supported chart types.
   */
  getSupportedTypes(): ChartType[]

  /**
   * Registers a plugin.
   */
  registerPlugin?(plugin: unknown): void

  /**
   * Sets global defaults.
   */
  setDefaults?(defaults: Partial<ChartConfig>): void
}

DataPoint

Data point for a chart.

interface DataPoint {
  /**
   * X-axis value or label.
   */
  x: string | number | Date

  /**
   * Y-axis value.
   */
  y: number

  /**
   * Optional secondary value (for bubble charts, etc.).
   */
  r?: number

  /**
   * Optional label override.
   */
  label?: string

  /**
   * Optional color override.
   */
  color?: string

  /**
   * Additional metadata.
   */
  meta?: Record<string, unknown>
}

Dataset

Dataset for a chart.

interface Dataset {
  /**
   * Dataset label.
   */
  label: string

  /**
   * Data points.
   */
  data: (number | DataPoint)[]

  /**
   * Background color(s).
   */
  backgroundColor?: string | string[]

  /**
   * Border color(s).
   */
  borderColor?: string | string[]

  /**
   * Border width.
   */
  borderWidth?: number

  /**
   * Fill area under line.
   */
  fill?: boolean | string

  /**
   * Line tension (0 = straight, 1 = curved).
   */
  tension?: number

  /**
   * Point radius.
   */
  pointRadius?: number

  /**
   * Point style.
   */
  pointStyle?: 'circle' | 'cross' | 'rect' | 'triangle' | 'star'

  /**
   * Show/hide dataset.
   */
  hidden?: boolean

  /**
   * Stack group (for stacked charts).
   */
  stack?: string

  /**
   * Y-axis ID (for multi-axis charts).
   */
  yAxisID?: string

  /**
   * X-axis ID (for multi-axis charts).
   */
  xAxisID?: string

  /**
   * Order (z-index).
   */
  order?: number
}

FontConfig

Chart font settings (family, size, weight, style).

interface FontConfig {
  family?: string
  size?: number
  weight?: 'normal' | 'bold' | number
  style?: 'normal' | 'italic'
}

LegendConfig

Chart legend settings (display, position, alignment, label styling, click handler).

interface LegendConfig {
  /**
   * Display legend.
   */
  display?: boolean

  /**
   * Position.
   */
  position?: 'top' | 'bottom' | 'left' | 'right' | 'chartArea'

  /**
   * Align.
   */
  align?: 'start' | 'center' | 'end'

  /**
   * Labels configuration.
   */
  labels?: {
    color?: string
    font?: FontConfig
    padding?: number
    usePointStyle?: boolean
    boxWidth?: number
    boxHeight?: number
  }

  /**
   * Click handler.
   */
  onClick?: (event: unknown, legendItem: unknown, legend: unknown) => void
}

TooltipConfig

Chart tooltip settings (mode, position, colors, border, padding, custom callbacks).

interface TooltipConfig {
  /**
   * Enable tooltips.
   */
  enabled?: boolean

  /**
   * Tooltip mode.
   */
  mode?: 'point' | 'nearest' | 'index' | 'dataset' | 'x' | 'y'

  /**
   * Intersect.
   */
  intersect?: boolean

  /**
   * Position.
   */
  position?: 'average' | 'nearest'

  /**
   * Background color.
   */
  backgroundColor?: string

  /**
   * Title color.
   */
  titleColor?: string

  /**
   * Body color.
   */
  bodyColor?: string

  /**
   * Border color.
   */
  borderColor?: string

  /**
   * Border width.
   */
  borderWidth?: number

  /**
   * Padding.
   */
  padding?: number

  /**
   * Custom callbacks.
   */
  callbacks?: {
    title?: (context: unknown) => string | string[]
    label?: (context: unknown) => string | string[]
    footer?: (context: unknown) => string | string[]
  }
}

Types

ChartType

Available chart visualization types (line, bar, pie, doughnut, area, scatter, radar, polar).

type ChartType =
  | 'line'
  | 'bar'
  | 'pie'
  | 'doughnut'
  | 'area'
  | 'scatter'
  | 'bubble'
  | 'radar'
  | 'polar'
  | 'heatmap'
  | 'treemap'
  | 'funnel'
  | 'gauge'
  | 'candlestick'

Functions

createAreaChart(container, config)

Creates an area chart (shorthand that sets type to 'area').

function createAreaChart(
  container: HTMLCanvasElement | HTMLElement,
  config: Omit<ChartConfig, 'type'>,
): ChartInstance
  • container — The DOM element to render the chart into.
  • config — The chart configuration (type is set automatically).

Returns: The created area chart instance.

createBarChart(container, config)

Creates a bar chart (shorthand that sets type to 'bar').

function createBarChart(
  container: HTMLCanvasElement | HTMLElement,
  config: Omit<ChartConfig, 'type'>,
): ChartInstance
  • container — The DOM element to render the chart into.
  • config — The chart configuration (type is set automatically).

Returns: The created bar chart instance.

createChart(container, config)

Creates a chart using the active provider.

function createChart(container: HTMLCanvasElement | HTMLElement, config: ChartConfig): ChartInstance
  • container — The DOM element to render the chart into.
  • config — The chart configuration including type, data, and options.

Returns: The created chart instance with update and destroy methods.

createDoughnutChart(container, config)

Creates a doughnut chart (shorthand that sets type to 'doughnut').

function createDoughnutChart(
  container: HTMLCanvasElement | HTMLElement,
  config: Omit<ChartConfig, 'type'>,
): ChartInstance
  • container — The DOM element to render the chart into.
  • config — The chart configuration (type is set automatically).

Returns: The created doughnut chart instance.

createLineChart(container, config)

Creates a line chart (shorthand that sets type to 'line').

function createLineChart(
  container: HTMLCanvasElement | HTMLElement,
  config: Omit<ChartConfig, 'type'>,
): ChartInstance
  • container — The DOM element to render the chart into.
  • config — The chart configuration (type is set automatically).

Returns: The created line chart instance.

createPieChart(container, config)

Creates a pie chart (shorthand that sets type to 'pie').

function createPieChart(
  container: HTMLCanvasElement | HTMLElement,
  config: Omit<ChartConfig, 'type'>,
): ChartInstance
  • container — The DOM element to render the chart into.
  • config — The chart configuration (type is set automatically).

Returns: The created pie chart instance.

createRadarChart(container, config)

Creates a radar chart (shorthand that sets type to 'radar').

function createRadarChart(
  container: HTMLCanvasElement | HTMLElement,
  config: Omit<ChartConfig, 'type'>,
): ChartInstance
  • container — The DOM element to render the chart into.
  • config — The chart configuration (type is set automatically).

Returns: The created radar chart instance.

createScatterChart(container, config)

Creates a scatter chart (shorthand that sets type to 'scatter').

function createScatterChart(
  container: HTMLCanvasElement | HTMLElement,
  config: Omit<ChartConfig, 'type'>,
): ChartInstance
  • container — The DOM element to render the chart into.
  • config — The chart configuration (type is set automatically).

Returns: The created scatter chart instance.

createSimpleChartProvider(options)

Creates the built-in placeholder chart provider. It does NOT draw real charts: every createChart paints a "placeholder — no chart provider bonded" notice onto the canvas and logs a one-time, actionable console.warn, rather than silently pretending to render. No real chart provider ships with the fleet — to draw actual charts, implement the {@link ChartProvider} interface around a real library (Chart.js / Recharts / D3) and wire it with bond('charts', provider) (or setProvider(provider)) at startup, before any create*Chart call.

function createSimpleChartProvider(options?: SimpleChartProviderOptions): ChartProvider
  • options — Optional overrides for the placeholder label/description text.

Returns: A placeholder chart provider — renders a non-functional notice, not a chart.

generateColors(count, palette)

Generates colors for a dataset.

function generateColors(
  count: number,
  palette?: 'default' | 'pastel' | 'vivid' | 'cool' | 'warm' | 'monochrome',
): string[]
  • count — The number of colors to generate.
  • palette — The named color palette to draw from.

Returns: An array of hex color strings cycling through the palette.

getColor(index, palette)

Gets a color from a palette.

function getColor(
  index: number,
  palette?: 'default' | 'pastel' | 'vivid' | 'cool' | 'warm' | 'monochrome',
): string
  • index — The color index (wraps around if it exceeds palette length).
  • palette — The named color palette to pick from.

Returns: The hex color string at the given index.

getProvider()

Gets the current chart provider. Falls back to the built-in placeholder provider if none has been bonded — that fallback does not draw real charts and warns once when it first renders (see {@link createSimpleChartProvider}). Bond a real ChartProvider before any create*Chart call to draw actual charts.

function getProvider(): ChartProvider

Returns: The active chart provider instance.

hasProvider()

Checks if a chart provider has been bonded.

function hasProvider(): boolean

Returns: Whether a chart provider is currently registered.

setProvider(provider)

Sets the chart provider.

function setProvider(provider: ChartProvider): void
  • provider — The chart provider implementation to bond.

Constants

colorPalettes

Color palette presets.

const colorPalettes: {
  default: string[]
  pastel: string[]
  vivid: string[]
  cool: string[]
  warm: string[]
  monochrome: string[]
}

provider

Default chart provider — the built-in placeholder provider. It does NOT draw real charts: it paints a "no chart provider bonded" notice and warns once (see {@link createSimpleChartProvider}). Exported only so apps can name it explicitly; it is NOT a shippable renderer. To draw real charts, implement the ChartProvider interface around a real library (Chart.js / Recharts / D3) and bond that instead with bond('charts', provider) (equivalent to setProvider), matching the convention of other bondable feature packages (e.g. @molecule/app-data-table-*).

const provider: ChartProvider

Injection Notes

Requirements

Peer dependencies:

  • @molecule/app-bond ^1.0.1
  • @molecule/app-i18n ^1.0.1

Runtime Dependencies

  • @molecule/app-bond
  • @molecule/app-i18n

The built-in default provider does NOT draw real charts. If no provider is bonded, every create*Chart call paints a non-functional placeholder notice onto the canvas (e.g. "bar chart — placeholder" / "No chart provider bonded") and logs a one-time, actionable console.warn — it never silently pretends to render. For real charts, bond @molecule/app-charts-chartjs (Chart.js — line/bar/pie/doughnut/area/scatter/bubble/radar/polar) at startup: import { provider } from '@molecule/app-charts-chartjs' then setProvider(provider) (same as bond('charts', provider)) in bonds.ts, BEFORE any component calls createChart. All create*Chart calls then route through it unchanged. (To use a different library, implement the ChartProvider interface around it — but the Chart.js bond covers the common cases.) Do not import a chart library directly in screens/components — keep it behind the provider so it stays swappable.

E2E Tests

Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:

  • Every chart on the app's screens renders with real data — no blank canvas, no NaN/undefined axis labels.
  • Plotted values match the data: spot-check at least one point/bar/slice against a number you can verify elsewhere in the UI.
  • Charts update when their inputs change (date range, filter, or a newly created record that should appear).
  • An empty dataset renders an empty state or zeroed axes — not a crash or a stale chart from previous data.
  • Tooltips and legends (where enabled) show the correct labels and values on hover.
  • Resizing the window/panel keeps charts legible (no overflow, no zero-height canvas).

Translations

Translation strings are provided by @molecule/app-locales-charts.