Widgets & charts

Five widget types. A widget's renderConfig shape depends on its type.

kpi_card

ts
interface KpiCardRenderConfig {
  format?: 'number' | 'currency' | 'percentage';
  currencySymbol?: string;   // falls back to settings.numberFormat.currencySymbol
  prefix?: string;
  suffix?: string;
  comparison?: { field: string; type: 'percentage' | 'absolute' };
  variant?: 'solid' | 'gradient';
  icon?: 'trending_up' | 'dollar' | 'users' | 'package' | 'activity' | 'percent' | 'gauge';
}

echarts

ts
interface EchartsRenderConfig {
  chartType: ChartType;        // see the catalog below
  smooth?: boolean;            // line/area
  showArea?: boolean;          // line/area
  stacked?: boolean;           // bar
  seriesStyles?: { field: string; color?: string; aggregation?: Aggregation }[];
  xAxisLabel?: string;
  yAxisLabel?: string;
  legendPosition?: 'top' | 'bottom' | 'none';
  showGridLines?: boolean;
  gaugeMin?: number;           // gauge only
  gaugeMax?: number;           // gauge only
  funnelSort?: 'ascending' | 'descending' | 'none'; // funnel only
  showInsight?: boolean;       // auto-written English caption, default true
  echartsOptionsCustom?: Record<string, unknown>; // merged over the generated option
}

The 25-chart catalog

GroupChart types
Trendline, area, stacked_area
Comparisonbar, horizontal_bar, stacked_bar, waterfall
Part-to-wholepie, donut, rose, treemap, sunburst
Correlationscatter, bubble
Multi-dimensionalradar, polar_bar
Distribution licensedheatmap, calendar_heatmap, boxplot
Relationships & flow licensedgraph, sankey, parallel
Specialized licensedgauge, funnel, candlestick

Sub-categories. Standard-axis charts (line/bar/…) accept a second dimension: the first becomes the x-axis, the second pivots into one series per value (e.g. region × product). Treemap and sunburst instead accept an ordered list of dimensions — each one nests a level deeper (region → product → SKU), with no limit on depth.

graph and sankey read dimensions[0] as the source field and dimensions[1] as the target field, with the first metric as edge weight. candlestick reads its four metrics in [open, close, low, high] order.

table

ts
interface TableRenderConfig {
  columns: TableColumn[];
  virtualScroll?: boolean;   // windows over the full filtered set client-side
  showQuickFilter?: boolean;
  striped?: boolean;
  compact?: boolean;
  rowClickable?: boolean;    // emits a row_click DashboardActionEvent
  defaultSort?: { field: string; direction: 'asc' | 'desc' };
  rowHeight?: number;        // default 36 (28 when compact)
}

interface TableColumn {
  field: string;
  header: string;
  width?: number;
  align?: 'left' | 'center' | 'right';
  sortable?: boolean;
  format?: 'text' | 'number' | 'currency' | 'percentage' | 'date' | 'chip' | 'image';
  decimals?: number;         // number/currency/percentage, default 2
  pinned?: boolean;
  colorField?: string;       // another field holding a CSS color for this cell/chip
}

format: 'chip' renders the value as a colored pill — explicit color via colorField, or a deterministic hash of the text when unset. format: 'image' renders the cell value as a thumbnail <img> src.

filter_panel

ts
interface FilterPanelRenderConfig {
  filterRefIds: string[]; // which globalFilters this panel renders controls for
}

markdown

ts
interface MarkdownRenderConfig {
  content: string; // headings, **bold**, *italic*, [links](url) — minimal, dependency-free
}