Real charts, no chart library

The widget draws a stat tile or a table on its own. Anything richer is one host option — and it does not need a dependency.

This page loads sgiant-ai-widget-charts.global.js — a 3.8 kB opt-in bundle that is not part of the widget — and hands its renderer to renderChartFallback. No chart library. The same renderer is importable as sgiant-ai-widget/charts with a bundler, so this page, a WordPress plugin and a third-party embed run one implementation instead of three copies drifting.

Animated bars

Bars grow from the baseline on first paint.

{"type":"widget","spec":{"title":"Bookings by channel","chartType":"breakdown"},
 "rows":[{"label":"Direct","value":182},{"label":"Booking.com","value":147},
         {"label":"Expedia","value":83},{"label":"Walk-in","value":24}]}

Animated line, with a comparison overlay

The line draws itself left to right. comparisonRows is the prior period — the widget passes it through as a fourth argument, and this renderer draws it dashed behind.

{"type":"widget","spec":{"title":"Revenue, last 8 weeks","chartType":"time_series"},
 "rows":[{"label":"W1","value":18},…],
 "comparisonRows":[{"label":"W1","value":14},…]}

A donut

Same seam, different chartType. Your renderer decides what each type means — the widget only routes it.

{"type":"widget","spec":{"title":"Traffic mix","chartType":"donut"},
 "rows":[{"label":"Organic","value":54},{"label":"Paid","value":28},
         {"label":"Referral","value":18}]}

What the option looks like

Return an optional disposer and the widget calls it when that message is cleared, so you can tear down anything you attached. If your renderer throws, the widget falls through to its built-in table rather than losing the turn.

// With a bundler
import { createChartFallback } from "sgiant-ai-widget/charts";
createAiChatWidget({ renderChartFallback: createChartFallback() });

// Or, with no build step at all — this page does exactly this
<script src="…/sgiant-ai-widget.global.js"></script>
<script src="…/sgiant-ai-widget-charts.global.js"></script>
<script>
  SgiantAiWidget.createAiChatWidget({
    renderChartFallback: SgiantAiWidgetCharts.createChartFallback(),
  });
</script>

It draws time_series, breakdown and donut. It throws for kpi, table, pivot_grid, heatmap, scatter and content — which the widget catches and renders with its own built-in instead. A bad heatmap made of rectangles is worse than a readable table of the same numbers, and a kpi is better as a stat tile than as a chart of one bar.

Eight dashboard widget types exist; this draws three. It is a floor for surfaces with no charting stack — a plain embed, a WordPress admin page. A React app with real chart components should mount those through renderDataWidget instead, which is what the sgiant dashboards and the hub do.