KPI indicator
KpiSchema is a KPI card: solid colored background, an icon, a title,
a large value, and a caption.
iconis the name of a Google Material Symbols icon (e.g.bar_chart,attach_money,warning) or"none"— the panel's icon picker is searchable both by technical name and by a plain-language label in the activelocale.title/value/subtitleare plain text (same{path}/{FUNCTION(...)}syntax as a standalone text field) — with noBindingof their own, resolved directly against the whole document at generation time.
Style
titleFontSize/valueFontSize/subtitleFontSize/iconSize(pt) — each defaults to the card's original fixed size (8/20/8/14pt) when absent, so existing templates never change appearance.borderRadius(0–100, a percentage) — corner rounding relative to the card's own smaller side (0 = square corners, 100 = a full "pill" shape). Defaults to ~16%, matching the card's original fixed 8pt radius at its default size.
Optional elements
title/value/subtitle are optional — remove any of them (or the
icon, via icon: "none") and it simply isn't drawn, in the editor and
in the generated PDF. Select the card alone (not part of a multi-select)
and the Fields tab shows its 4 sub-elements — icon/title/value/subtitle
— each with a "+"/trash button to add it back or remove it.
Custom position, lock, and reset
Each sub-element can be dragged to its own position on the canvas,
independent of the other three — stored as iconOffset/titleOffset/
valueOffset/subtitleOffset ({ x, y } in mm, relative to the card's
top-left corner). Left absent, a sub-element uses the card's original
fixed layout — every existing template keeps its exact appearance.
A sub-element is locked by default (iconLocked/titleLocked/
valueLocked/subtitleLocked, absent or true = locked) — click its
lock icon in the Fields tab's sub-element list to unlock it before it
can be dragged. Clicking a sub-element (in the Fields list or directly
on the canvas) focuses it: the Style tab then shows only that element's
own controls (font size, icon picker, number format...), with a
"← Card style" link back to the whole-card style and, once it has a
custom position, a "Reset position" button that clears the offset and
returns it to the default layout.
Binding to an array (aggregation)
A KPI's value is a free-text template by default (same {path}/
{FUNCTION(...)} syntax as text). It can instead be bound directly to
an array — same idea as a chart — via a Binding of type kpi:
const binding: Binding = {
schemaName: "total_sales",
type: "kpi",
path: "salesByAgent",
valueColumn: "value", // ignored when aggregation is "count"
aggregation: "sum", // "sum" | "count" | "avg" | "min" | "max"
filters: [[{ column: "status", op: "eq", value: "closed" }]], // optional, same shape as a chart's
};
When a kpi binding exists for a card, it overrides the free-text
value template entirely — the aggregated number becomes the value,
title/subtitle are unaffected. Without a kpi binding, the card
behaves exactly as before (free-text value).
Number format
numberFormat (Data tab) reformats value when it resolves to a
plain number — it never touches text with a prefix/suffix (e.g.
"R$ 42" isn't a plain number, so it's left alone):
numberFormat | Example |
|---|---|
"none" (default) | Shows the resolved value exactly as-is. |
"plain" | 10000 — comma decimal if the number has one, no thousands separator. |
"grouped" | 10.000 — same, with a thousands separator. |
Multi-select bulk editing
Selecting several KPI cards together (Ctrl/Cmd+click) unlocks
bulk-editing their shared Style (color, font sizes, icon, border
radius — applies to every selected card at once); the per-card Data
content (title/value/caption) stays locked to avoid overwriting
different cards' own text, except numberFormat, which is shared and
stays editable.