Skip to content

Chart integration

yk-grid ships a yk-grid/chart subpath with data-shaping helpers that feed filtered grid rows into a chart library. The helpers are tree-shakeable and carry zero runtime dependency on any chart library — you install and render the chart yourself.

The example below uses AG-Charts Community (MIT licence, canvas-based), but the same pattern works with any library that accepts a flat data array (Recharts, Victory, Chart.js, etc.).


Install

bash
npm install ag-charts-react ag-charts-community

Register the AG-Charts module once at your app entry point:

ts
import { AllCommunityModule, ModuleRegistry } from 'ag-charts-community'
ModuleRegistry.registerModules([AllCommunityModule])

Basic pattern

tsx
import { useRef, useState, useMemo, useCallback } from 'react'
import { AgCharts } from 'ag-charts-react'
import type { AgChartOptions } from 'ag-charts-community'
import { DataGrid } from 'yk-grid'
import { projectRows } from 'yk-grid/chart'
import type { GridRef, ColumnDef } from 'yk-grid'

interface Transaction {
  id: string
  date: string
  amount: number
  revenue: number
  status: string
}

const columns: ColumnDef<Transaction>[] = [
  { id: 'date',    header: 'Date',    accessor: r => r.date },
  { id: 'amount',  header: 'Amount',  accessor: r => r.amount,  sortable: true, filterType: 'number' },
  { id: 'revenue', header: 'Revenue', accessor: r => r.revenue, sortable: true, filterType: 'number' },
  { id: 'status',  header: 'Status',  accessor: r => r.status,  filterable: true, filterType: 'select' },
]

export default function Page({ data }: { data: Transaction[] }) {
  const gridRef = useRef<GridRef<Transaction>>(null)

  // Seed with all rows; update whenever grid filters/sorts change.
  const [chartRows, setChartRows] = useState<Transaction[]>(data)

  const handleStateChange = useCallback(() => {
    setChartRows(gridRef.current?.getProcessedRows() ?? [])
  }, [])

  const chartOptions = useMemo<AgChartOptions>(() => ({
    data: projectRows(chartRows, columns, { columnIds: ['amount', 'revenue'] }),
    title: { text: 'Revenue vs Amount' },
    subtitle: { text: `${chartRows.length.toLocaleString()} rows` },
    series: [{ type: 'scatter', xKey: 'amount', yKey: 'revenue' }],
    axes: [
      { type: 'number', position: 'bottom', title: { text: 'Amount' } },
      { type: 'number', position: 'left',   title: { text: 'Revenue' } },
    ],
  }), [chartRows])

  return (
    <>
      <DataGrid<Transaction>
        ref={gridRef}
        data={data}
        columns={columns}
        getRowId={r => r.id}
        dataMode="client"
        onStateChange={handleStateChange}
      />
      <AgCharts options={chartOptions} />
    </>
  )
}

onStateChange fires whenever sorts, filters, grouping, or pagination change. getProcessedRows() returns all rows that pass the current filters (ignoring pagination), which is what the chart should reflect.


projectRows

ts
import { projectRows } from 'yk-grid/chart'
import type { ProjectRowsOptions, ProjectedRow } from 'yk-grid/chart'

projectRows<T>(
  rows: T[],
  columns: ColumnDef<T>[],
  opts?: ProjectRowsOptions,
): ProjectedRow[]

Maps each row to a flat { [columnId]: value } object — the shape chart libraries expect in their data array.

BehaviourDetail
null valuesOmitted from the object (key absent)
Date valuesCoerced to ISO string by default; pass { dateFormat: 'epoch' } for time axes
Invalid DateSkipped (treated like null)
columnIds subsetPass { columnIds: ['x', 'y'] } to project only the columns the chart needs — keeps data objects lean for wide grids

buildChartOptions

Sugar over projectRows that also assembles the series array:

ts
import { buildChartOptions } from 'yk-grid/chart'
import type { ChartSpec } from 'yk-grid/chart'

buildChartOptions<T>(input: BuildChartOptionsInput<T>): ChartSpec
tsx
import type { AgChartOptions } from 'ag-charts-community'

const spec = buildChartOptions({
  rows: chartRows,
  columns,
  xColumnId: 'date',
  yColumnIds: ['revenue', 'amount'],
  seriesType: 'bar',  // 'bar' | 'line' | 'area' | 'scatter' — default 'bar'
})

<AgCharts options={spec as AgChartOptions} />

buildChartOptions returns a ChartSpec — a plain structural type with no AG-Charts import. Cast to AgChartOptions at the call site if your chart library requires it.


ChartSpec type

ts
type ChartSpec = {
  data: ProjectedRow[]
  series: Array<{ type: string; xKey: string; yKey: string; yName: string }>
}

Structurally compatible with AgChartOptions. Spread or extend it to add title, subtitle, axes, or other chart-specific options before passing to <AgCharts>.


Server mode caveat

In dataMode="server", getProcessedRows() returns only the current page of data — the server has already filtered. The chart will reflect only what's loaded, not the full filtered set. This is documented behaviour for v1; full server-mode chart support is planned for a future release.

Released under the MIT Licence.