{
  "$schema": "https://microcharts.dev/catalog.schema.json",
  "package": "@microcharts/react",
  "homepage": "https://microcharts.dev",
  "howToRead": "Full API for a chart = sharedProps (grammar, layout, i18n) + charts[n].props (chart-specific). Interactive shared callbacks/flags apply ONLY when listed in charts[n].sharedInteractive (empty/missing ⇒ no shared interactive props). Chart-specific interactive props stay in charts[n].props with interactive:true (e.g. onWindowChange). Prefer docs URL + this file over memorized APIs.",
  "sharedProps": [
    {
      "name": "data",
      "type": "(number | null)[] | per-chart shape",
      "required": true,
      "description": "The series. `null` / `NaN` are gaps, never zeros. The one required prop; each chart documents its own shape when it isn't a plain number array."
    },
    {
      "name": "domain",
      "type": "[min, max]",
      "required": false,
      "description": "Fix the value range instead of auto-fitting."
    },
    {
      "name": "color",
      "type": "string",
      "required": false,
      "description": "Mark color: any CSS color or a token (`\"var(--mc-accent)\"`). Semantic tokens keep their meaning."
    },
    {
      "name": "title",
      "type": "string",
      "required": false,
      "description": "Names the chart — rendered as an SVG `<title>`, so it becomes the accessible name and the native hover tooltip, not visible text on the page."
    },
    {
      "name": "summary",
      "type": "string | false",
      "required": false,
      "description": "Override the auto-generated accessible sentence, or pass `false` to mark the chart decorative."
    },
    {
      "name": "format",
      "type": "Intl.NumberFormatOptions | (n) => string",
      "required": false,
      "description": "How numbers render in labels and summaries."
    },
    {
      "name": "positive",
      "type": "\"up\" | \"down\"",
      "required": false,
      "description": "Which direction is good, so color and arrows point the honest way (lower latency is `\"down\"`)."
    },
    {
      "name": "label",
      "type": "per chart",
      "required": false,
      "description": "A short direct label next to the mark, in a reserved gutter — never an axis or legend."
    },
    {
      "name": "dots",
      "type": "per chart",
      "required": false,
      "description": "Which individual points to emphasize (e.g. `\"minmax\"` on a line)."
    },
    {
      "name": "width",
      "type": "number | string",
      "required": false,
      "description": "Rendered width. Omit both dimensions to size from the container."
    },
    {
      "name": "height",
      "type": "number | string",
      "required": false,
      "description": "Rendered height."
    },
    {
      "name": "className",
      "type": "string",
      "required": false,
      "description": "Class on the chart root."
    },
    {
      "name": "style",
      "type": "CSSProperties",
      "required": false,
      "description": "Inline style on the chart root (a common place to set width/height)."
    },
    {
      "name": "id",
      "type": "string",
      "required": false,
      "description": "Opts into `<title>`/`<desc>` + `aria-labelledby` naming instead of the default `aria-label`."
    },
    {
      "name": "locale",
      "type": "string | string[]",
      "required": false,
      "description": "BCP-47 locale for number and date formatting (defaults to the runtime locale)."
    },
    {
      "name": "strings",
      "type": "SummaryStrings",
      "required": false,
      "description": "Override the summary/label string templates for translation."
    },
    {
      "name": "seriesStrings",
      "type": "SeriesStrings",
      "required": false,
      "description": "Multi-series analog of `strings` — series/slot labels for charts that plot several series."
    },
    {
      "name": "animate",
      "type": "boolean",
      "required": false,
      "description": "Opt-in entrance motion when the chart mounts client-side — add `import \"@microcharts/react/motion\"` once. Inert on the server, on hydrated server HTML, and under `prefers-reduced-motion`.",
      "interactive": true
    },
    {
      "name": "live",
      "type": "boolean",
      "required": false,
      "description": "Announce value changes through a polite live region as the data updates (default on), on the entries whose value can change without the reader touching the chart. Charts that stream a fast-moving number throttle their own announcements — EtaBar exposes the interval as `announceEvery`.",
      "interactive": true
    },
    {
      "name": "onActive",
      "type": "(datum: MicroDatum | null) => void",
      "required": false,
      "description": "The active unit changed — the one under the pointer or the keyboard focus. `null` when the chart is cleared (pointer leaves, focus blurs, Escape). Payload is `MicroDatum` — `{ index, value, label?, formatted? }`, where `index` identifies the navigable unit, `value` is its primary encoded number (`null` for an empty unit), and `formatted` is the exact string the chart's own readout chip would show. Pair with `readout={false}` to render that value outside the chart.",
      "interactive": true
    },
    {
      "name": "onSelect",
      "type": "(datum: MicroDatum | null) => void",
      "required": false,
      "description": "A unit was activated — click, tap, `Enter` or `Space` — pinning it so it survives blur. `null` when the selection is cleared (re-activating the same unit, or `Escape`). Same `MicroDatum` payload as `onActive`.",
      "interactive": true
    },
    {
      "name": "selectedIndex",
      "type": "number | null",
      "required": false,
      "description": "Controlled selected unit — an index into the chart's navigable units, or `null` for none. Pass it to own the selection; pair with `onSelect`.",
      "interactive": true
    },
    {
      "name": "defaultSelectedIndex",
      "type": "number | null",
      "required": false,
      "description": "Uncontrolled initial selection. Ignored once `selectedIndex` is set. Use it to open a chart with one unit already pinned.",
      "interactive": true
    },
    {
      "name": "readout",
      "type": "boolean",
      "required": false,
      "description": "Show the floating value chip that follows the pointer/focus (default `true`). `false` suppresses only the chip — the hover crosshair, keyboard roving, live-region announcements, and both callbacks keep working — so you can render `datum.formatted` in your own layout instead.",
      "interactive": true
    }
  ],
  "charts": [
    {
      "name": "Sparkline",
      "slug": "sparkline",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/sparkline",
      "staticImport": "@microcharts/react/sparkline",
      "interactiveImport": "@microcharts/react/sparkline/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[]",
      "primaryEncoding": "position (length along a line)",
      "bestFor": [
        "inline trend",
        "table-cell trend",
        "KPI sparkline",
        "dense dashboards"
      ],
      "avoidFor": [
        "part-to-whole",
        "exact category comparison"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "The series. null/NaN are gaps."
        },
        {
          "name": "curve",
          "type": "\"linear\" | \"smooth\" | \"step\"",
          "required": false,
          "description": "Line shape."
        },
        {
          "name": "fill",
          "type": "boolean",
          "required": false,
          "description": "Zero-anchored area under the line."
        },
        {
          "name": "band",
          "type": "[number, number]",
          "required": false,
          "description": "Constant normal-range band."
        },
        {
          "name": "dots",
          "type": "\"auto\" | \"minmax\" | \"none\"",
          "required": false,
          "description": "Endpoint or min/max dots."
        },
        {
          "name": "label",
          "type": "\"none\" | \"last\" | \"minmax\"",
          "required": false,
          "description": "Direct value labels: endpoint, or the extremes."
        },
        {
          "name": "maxPoints",
          "type": "number",
          "required": false,
          "description": "Line-point cap (default 200); longer series decimate min/max-preserving."
        },
        {
          "name": "title",
          "type": "string",
          "required": false,
          "description": "Accessible name; joins the auto summary."
        },
        {
          "name": "summary",
          "type": "string | false",
          "required": false,
          "description": "Override or disable the auto summary."
        }
      ],
      "examples": [
        {
          "title": "Weekly revenue",
          "code": "import { Sparkline } from \"@microcharts/react/sparkline\";\n\n<Sparkline data={[3, 5, 4, 8, 6, 9]} title=\"Weekly revenue\" />"
        }
      ]
    },
    {
      "name": "SparkBar",
      "slug": "sparkbar",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/sparkbar",
      "staticImport": "@microcharts/react/sparkbar",
      "interactiveImport": "@microcharts/react/sparkbar/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[]",
      "primaryEncoding": "length (bar height from a zero baseline)",
      "bestFor": [
        "discrete magnitudes",
        "win–loss streaks",
        "period-over-period counts"
      ],
      "avoidFor": [
        "continuous trend shape",
        "many hundreds of points"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Values; negatives dip below the baseline."
        },
        {
          "name": "mode",
          "type": "\"bar\" | \"winloss\"",
          "required": false,
          "description": "Magnitude bars, or a win/loss/tie streak (sign only)."
        },
        {
          "name": "gap",
          "type": "number",
          "required": false,
          "description": "Empty fraction of each slot (0–0.9)."
        },
        {
          "name": "label",
          "type": "\"none\" | \"last\"",
          "required": false,
          "description": "Direct endpoint value label."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "\"up\" (default); \"down\" flips which sign is good."
        },
        {
          "name": "title",
          "type": "string",
          "required": false,
          "description": "Accessible name; joins the auto summary."
        },
        {
          "name": "summary",
          "type": "string | false",
          "required": false,
          "description": "Override or disable the auto summary."
        },
        {
          "name": "locale",
          "type": "string | string[]",
          "required": false,
          "description": "BCP 47 locale(s) for the endpoint label and summary."
        }
      ],
      "examples": [
        {
          "title": "Deploys per day",
          "code": "import { SparkBar } from \"@microcharts/react/sparkbar\";\n\n<SparkBar data={[4, 6, 2, 8, 5, 9]} title=\"Deploys per day\" />"
        }
      ]
    },
    {
      "name": "Delta",
      "slug": "delta",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/delta",
      "staticImport": "@microcharts/react/delta",
      "interactiveImport": "@microcharts/react/delta/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onSelect"
      ],
      "dataShape": "number (+ optional from)",
      "primaryEncoding": "text + direction glyph (▲/▼)",
      "bestFor": [
        "KPI change",
        "period-over-period %",
        "inline metric movement"
      ],
      "avoidFor": [
        "showing a series",
        "magnitude across many items"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The change, or current value when from is set."
        },
        {
          "name": "from",
          "type": "number",
          "required": false,
          "description": "Prior value; Delta shows the percent change."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Which direction is good (colors only)."
        },
        {
          "name": "format",
          "type": "Intl.NumberFormatOptions | fn",
          "required": false,
          "description": "Number formatting."
        },
        {
          "name": "locale",
          "type": "string | string[]",
          "required": false,
          "description": "BCP 47 locale(s) for the formatted number."
        },
        {
          "name": "summary",
          "type": "string | false",
          "required": false,
          "description": "Override or disable the auto summary."
        }
      ],
      "examples": [
        {
          "title": "Revenue change",
          "code": "import { Delta } from \"@microcharts/react/delta\";\n\n<Delta value={0.124} title=\"Revenue vs last week\" />"
        }
      ]
    },
    {
      "name": "Bullet",
      "slug": "bullet",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/bullet",
      "staticImport": "@microcharts/react/bullet",
      "interactiveImport": "@microcharts/react/bullet/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onSelect",
        "readout"
      ],
      "dataShape": "value + target + bands",
      "primaryEncoding": "position (measure length vs a target tick)",
      "bestFor": [
        "progress to goal",
        "SLA / budget vs target",
        "KPI with thresholds"
      ],
      "avoidFor": [
        "trends over time",
        "distributions"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The measured value."
        },
        {
          "name": "target",
          "type": "number",
          "required": false,
          "description": "Target tick to compare against."
        },
        {
          "name": "bands",
          "type": "number[]",
          "required": false,
          "description": "Ascending qualitative thresholds."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Explicit [0, max]; auto-fit otherwise."
        },
        {
          "name": "label",
          "type": "\"none\" | \"value\" | \"target\" | \"both\"",
          "required": false,
          "description": "Value/target readout in a right gutter (default none)."
        },
        {
          "name": "title",
          "type": "string",
          "required": false,
          "description": "Accessible name; joins the auto summary."
        },
        {
          "name": "summary",
          "type": "string | false",
          "required": false,
          "description": "Override or disable the auto summary."
        }
      ],
      "examples": [
        {
          "title": "Quota attainment",
          "code": "import { Bullet } from \"@microcharts/react/bullet\";\n\n<Bullet value={72} target={80} bands={[50, 90]} title=\"Quota\" />"
        }
      ]
    },
    {
      "name": "ActivityGrid",
      "slug": "activity-grid",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/activity-grid",
      "staticImport": "@microcharts/react/activity-grid",
      "interactiveImport": "@microcharts/react/activity-grid/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[]",
      "primaryEncoding": "color intensity (discrete levels) over a grid",
      "bestFor": [
        "daily activity",
        "streaks and cadence",
        "seasonality at a glance"
      ],
      "avoidFor": [
        "exact values",
        "precise comparison between two cells"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Ordered values, one per cell."
        },
        {
          "name": "layout",
          "type": "\"grid\" | \"strip\"",
          "required": false,
          "description": "7-row calendar or single strip."
        },
        {
          "name": "shape",
          "type": "\"square\" | \"round\" | \"dot\"",
          "required": false,
          "description": "Cell mark: crisp square, soft corners, or padded dot."
        },
        {
          "name": "anchor",
          "type": "string | Date",
          "required": false,
          "description": "First slot's calendar day (UTC) — pads the first column so weekday rows align."
        },
        {
          "name": "weekStart",
          "type": "0 | 1",
          "required": false,
          "description": "Start of week for anchor alignment (0 Sunday, 1 Monday)."
        },
        {
          "name": "cell",
          "type": "number",
          "required": false,
          "description": "Cell edge length in viewBox units."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Explicit range for level bucketing."
        },
        {
          "name": "title",
          "type": "string",
          "required": false,
          "description": "Accessible name; joins the auto summary."
        },
        {
          "name": "summary",
          "type": "string | false",
          "required": false,
          "description": "Override or disable the auto summary."
        }
      ],
      "examples": [
        {
          "title": "Commits this month",
          "code": "import { ActivityGrid } from \"@microcharts/react/activity-grid\";\n\n<ActivityGrid data={commits} title=\"Commits\" />"
        }
      ]
    },
    {
      "name": "TrendArrow",
      "slug": "trend-arrow",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/trend-arrow",
      "staticImport": "@microcharts/react/trend-arrow",
      "interactiveImport": "@microcharts/react/trend-arrow/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onSelect"
      ],
      "dataShape": "number (signed change)",
      "primaryEncoding": "glyph orientation (up / down / flat)",
      "bestFor": [
        "table direction columns",
        "dense dashboards",
        "inline movement cues"
      ],
      "avoidFor": [
        "exact magnitudes (use Delta)",
        "series shape (use Sparkline)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "Signed change; sign → direction, magnitude only via showValue/summary."
        },
        {
          "name": "flatBand",
          "type": "number",
          "required": false,
          "description": "Noise floor: |value| ≤ flatBand renders the flat glyph."
        },
        {
          "name": "glyph",
          "type": "\"arrow\" | \"triangle\" | \"chevron\"",
          "required": false,
          "description": "Mark weight: default legibility, dense cells, inline text."
        },
        {
          "name": "showValue",
          "type": "boolean",
          "required": false,
          "description": "Append the formatted value in a right gutter."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Which direction is good (colors only, never the glyph)."
        }
      ],
      "examples": [
        {
          "title": "Latency direction",
          "code": "import { TrendArrow } from \"@microcharts/react/trend-arrow\";\n\n<TrendArrow value={-0.08} positive=\"down\" title=\"Latency vs last week\" />"
        }
      ]
    },
    {
      "name": "StatusDot",
      "slug": "status-dot",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/status-dot",
      "staticImport": "@microcharts/react/status-dot",
      "interactiveImport": "@microcharts/react/status-dot/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onSelect"
      ],
      "dataShape": "\"ok\" | \"warn\" | \"error\" | \"off\" | \"busy\" (extensible)",
      "primaryEncoding": "paired glyph shape + semantic color",
      "bestFor": [
        "service lists",
        "inline state in a sentence",
        "monitoring rows"
      ],
      "avoidFor": [
        "quantities",
        "trends",
        "more than ~6 state kinds"
      ],
      "props": [
        {
          "name": "status",
          "type": "string",
          "required": true,
          "description": "Built-in ok | warn | error | off | busy, or a key of states."
        },
        {
          "name": "pulse",
          "type": "boolean",
          "required": false,
          "description": "Live-now halo (reduced-motion-gated)."
        },
        {
          "name": "states",
          "type": "Record<string, { glyph; token; label }>",
          "required": false,
          "description": "Extend the vocabulary; the shape+color pairing is preserved."
        },
        {
          "name": "color",
          "type": "string",
          "required": false,
          "description": "Recolors the active state; never reshapes it."
        }
      ],
      "examples": [
        {
          "title": "Service state",
          "code": "import { StatusDot } from \"@microcharts/react/status-dot\";\n\n<StatusDot status=\"ok\" title=\"API\" />"
        }
      ]
    },
    {
      "name": "HeatCell",
      "slug": "heat-cell",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/heat-cell",
      "staticImport": "@microcharts/react/heat-cell",
      "interactiveImport": "@microcharts/react/heat-cell/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onSelect",
        "readout"
      ],
      "dataShape": "number (+ shared domain)",
      "primaryEncoding": "discrete color step",
      "bestFor": [
        "table-cell matrices",
        "calendar-like grids you lay out yourself",
        "intensity chips"
      ],
      "avoidFor": [
        "precise value comparison",
        "per-cell auto-scaling (share one domain!)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The value to calibrate."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Calibration scale — defaults to [0, 1]; every cell in a grid must share one."
        },
        {
          "name": "steps",
          "type": "number",
          "required": false,
          "description": "Discrete perceptual steps (default 5, shared with ActivityGrid)."
        },
        {
          "name": "shape",
          "type": "\"square\" | \"round\" | \"dot\"",
          "required": false,
          "description": "Shared cell vocabulary."
        },
        {
          "name": "label",
          "type": "\"value\" | \"none\"",
          "required": false,
          "description": "Centered number when the cell doubles as a chip."
        }
      ],
      "examples": [
        {
          "title": "Load cell",
          "code": "import { HeatCell } from \"@microcharts/react/heat-cell\";\n\n<HeatCell value={42} domain={[0, 100]} title=\"Load\" />"
        }
      ]
    },
    {
      "name": "Progress",
      "slug": "progress",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/progress",
      "staticImport": "@microcharts/react/progress",
      "interactiveImport": "@microcharts/react/progress/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onSelect"
      ],
      "dataShape": "number of max (optionally segmented)",
      "primaryEncoding": "zero-anchored bar length + direct % label",
      "bestFor": [
        "KPI cards",
        "table completion columns",
        "step counts (segments)"
      ],
      "avoidFor": [
        "icon-size slots (use ProgressRing)",
        "composition (use SegmentedBar)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The progressed amount."
        },
        {
          "name": "max",
          "type": "number",
          "required": false,
          "description": "Denominator (default 1)."
        },
        {
          "name": "segments",
          "type": "number",
          "required": false,
          "description": "Discrete-chunk track — the chart says step count, not ratio."
        },
        {
          "name": "label",
          "type": "\"percent\" | \"value\" | \"fraction\" | \"none\"",
          "required": false,
          "description": "The direct label; percent is the default datum."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "down = burn-down wording (summary only; the bar stays factual)."
        }
      ],
      "examples": [
        {
          "title": "Onboarding",
          "code": "import { Progress } from \"@microcharts/react/progress\";\n\n<Progress value={0.68} title=\"Onboarding\" />"
        }
      ]
    },
    {
      "name": "RugStrip",
      "slug": "rug-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/rug-strip",
      "staticImport": "@microcharts/react/rug-strip",
      "interactiveImport": "@microcharts/react/rug-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[] (raw observations)",
      "primaryEncoding": "tick position; density via ink accumulation",
      "bestFor": [
        "\"you are here\" in a band",
        "distribution beside a stat",
        "margin composition"
      ],
      "avoidFor": [
        "> 400 observations (HistogramStrip)",
        "trends over time (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Raw observations — position = value."
        },
        {
          "name": "markValue",
          "type": "number",
          "required": false,
          "description": "One value emphasized against the field."
        },
        {
          "name": "orientation",
          "type": "\"horizontal\" | \"vertical\"",
          "required": false,
          "description": "Vertical rugs sit beside distributions."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Fix the scale across rows (rugs mislead worst under per-row autoscale)."
        }
      ],
      "examples": [
        {
          "title": "Salary band",
          "code": "import { RugStrip } from \"@microcharts/react/rug-strip\";\n\n<RugStrip data={salaries} markValue={yourOffer} title=\"Pay band\" />"
        }
      ]
    },
    {
      "name": "MiniBar",
      "slug": "mini-bar",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/mini-bar",
      "staticImport": "@microcharts/react/mini-bar",
      "interactiveImport": "@microcharts/react/mini-bar/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value }[]",
      "primaryEncoding": "bar length, zero-anchored",
      "bestFor": [
        "per-row category mix in tables",
        "small comparisons in cards"
      ],
      "avoidFor": [
        "> 8 categories (full bar chart)",
        "time series (SparkBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; value }[]",
          "required": true,
          "description": "Categories in meaningful order."
        },
        {
          "name": "order",
          "type": "\"data\" | \"desc\" | \"asc\"",
          "required": false,
          "description": "Ranking read vs positional read — data-facing, not styling."
        },
        {
          "name": "highlight",
          "type": "number | string",
          "required": false,
          "description": "Index or label to emphasize."
        },
        {
          "name": "orientation",
          "type": "\"horizontal\" | \"vertical\"",
          "required": false,
          "description": "Rows for wider, shorter cells."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Engages pos/neg tokens on signed data."
        },
        {
          "name": "label",
          "type": "\"none\" | \"max\"",
          "required": false,
          "description": "Peak-value readout (vertical only; default \"none\")."
        }
      ],
      "examples": [
        {
          "title": "Regional mix",
          "code": "import { MiniBar } from \"@microcharts/react/mini-bar\";\n\n<MiniBar data={regions} title=\"Sales by region\" />"
        }
      ]
    },
    {
      "name": "PictogramRow",
      "slug": "pictogram-row",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/pictogram-row",
      "staticImport": "@microcharts/react/pictogram-row",
      "interactiveImport": "@microcharts/react/pictogram-row/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex"
      ],
      "dataShape": "value of total (units)",
      "primaryEncoding": "filled-unit count",
      "bestFor": [
        "seats and slots in a sentence",
        "ratings",
        "capacity rows"
      ],
      "avoidFor": [
        "> 20 units (Progress)",
        "continuous ratios (Progress)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "Filled units (may be fractional)."
        },
        {
          "name": "total",
          "type": "number",
          "required": true,
          "description": "Unit count."
        },
        {
          "name": "shape",
          "type": "\"dot\" | \"square\"",
          "required": false,
          "description": "Squares pack tighter in table cells."
        },
        {
          "name": "fractional",
          "type": "\"clip\" | \"round\"",
          "required": false,
          "description": "Clip shows the true partial unit; round for seat-like units."
        },
        {
          "name": "renderPoint",
          "type": "(unit) => ReactNode",
          "required": false,
          "description": "Custom unit glyph (star ratings) — the one sanctioned customization."
        }
      ],
      "examples": [
        {
          "title": "Committee seats",
          "code": "import { PictogramRow } from \"@microcharts/react/pictogram-row\";\n\n<PictogramRow value={5} total={8} title=\"Committee seats held\" />"
        }
      ]
    },
    {
      "name": "Seismogram",
      "slug": "seismogram",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/seismogram",
      "staticImport": "@microcharts/react/seismogram",
      "interactiveImport": "@microcharts/react/seismogram/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(number | null)[] (per-slot intensity; 0 = quiet)",
      "primaryEncoding": "tick presence (density) + height (intensity)",
      "bestFor": [
        "error bursts per service",
        "alert density",
        "activity texture in rows"
      ],
      "avoidFor": [
        "level tracking (Sparkline)",
        "labeled events (EventTimeline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "Per-slot event intensity; 0/null = quiet."
        },
        {
          "name": "mode",
          "type": "\"intensity\" | \"barcode\"",
          "required": false,
          "description": "Barcode collapses heights — pure occurrence density."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Polarity coloring of signed ticks."
        },
        {
          "name": "anomaly",
          "type": "number",
          "required": false,
          "description": "Flag spikes: |v| ≥ threshold flares in the alert token."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Fixed intensity scale across rows."
        }
      ],
      "examples": [
        {
          "title": "Error bursts",
          "code": "import { Seismogram } from \"@microcharts/react/seismogram\";\n\n<Seismogram data={burstsPerMinute} title=\"Error bursts\" />"
        }
      ]
    },
    {
      "name": "HeatStrip",
      "slug": "heat-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/heat-strip",
      "staticImport": "@microcharts/react/heat-strip",
      "interactiveImport": "@microcharts/react/heat-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(number | null)[]",
      "primaryEncoding": "discrete color step per time cell",
      "bestFor": [
        "per-tenant load rows",
        "intensity ribbons in tables",
        "dense time context"
      ],
      "avoidFor": [
        "exact shape (Sparkline)",
        "calendar rhythm (ActivityGrid)"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "Time-ordered values; null = no record (≠ zero)."
        },
        {
          "name": "steps",
          "type": "number",
          "required": false,
          "description": "Shared step-scale granularity (default 5)."
        },
        {
          "name": "shape",
          "type": "\"square\" | \"round\" | \"dot\"",
          "required": false,
          "description": "Shared cell vocabulary."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Cross-row calibration — share one domain per table."
        }
      ],
      "examples": [
        {
          "title": "Load per hour",
          "code": "import { HeatStrip } from \"@microcharts/react/heat-strip\";\n\n<HeatStrip data={hourlyLoad} domain={[0, 100]} title=\"Load per hour\" />"
        }
      ]
    },
    {
      "name": "DotPlot",
      "slug": "dot-plot",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/dot-plot",
      "staticImport": "@microcharts/react/dot-plot",
      "interactiveImport": "@microcharts/react/dot-plot/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value }[]",
      "primaryEncoding": "dot position on a common scale",
      "bestFor": [
        "KPI leaderboards",
        "named comparisons in cards",
        "rows where bars would lie"
      ],
      "avoidFor": [
        "> 7 rows",
        "time series (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; value }[]",
          "required": true,
          "description": "Named values."
        },
        {
          "name": "stem",
          "type": "boolean",
          "required": false,
          "description": "Hairline from zero — flips to a magnitude read (zero-anchored domain forced)."
        },
        {
          "name": "highlight",
          "type": "number | string",
          "required": false,
          "description": "Accent one category."
        },
        {
          "name": "label",
          "type": "\"value\" | \"none\"",
          "required": false,
          "description": "Value text beside each dot (drops out under 8-unit rows)."
        }
      ],
      "examples": [
        {
          "title": "Team leaderboard",
          "code": "import { DotPlot } from \"@microcharts/react/dot-plot\";\n\n<DotPlot data={team} title=\"Review scores\" />"
        }
      ]
    },
    {
      "name": "Dumbbell",
      "slug": "dumbbell",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/dumbbell",
      "staticImport": "@microcharts/react/dumbbell",
      "interactiveImport": "@microcharts/react/dumbbell/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label?, from, to }[]",
      "primaryEncoding": "two dot positions + connecting span",
      "bestFor": [
        "salary bands",
        "before/after per row",
        "ranges in tables"
      ],
      "avoidFor": [
        "many rows (Slope for crossings)",
        "the path between (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label?; from; to }[]",
          "required": true,
          "description": "Start/end pairs."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Direction valence for CHANGES; drop it for ranges (no valence)."
        },
        {
          "name": "label",
          "type": "\"value\" | \"none\"",
          "required": false,
          "description": "From/to values outside the dots (drop when the span is tight)."
        },
        {
          "name": "highlight",
          "type": "number | string",
          "required": false,
          "description": "Accent one row."
        }
      ],
      "examples": [
        {
          "title": "Salary band move",
          "code": "import { Dumbbell } from \"@microcharts/react/dumbbell\";\n\n<Dumbbell data={[{ from: 62000, to: 84000 }]} title=\"Band move\" />"
        }
      ]
    },
    {
      "name": "PairedBars",
      "slug": "paired-bars",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/paired-bars",
      "staticImport": "@microcharts/react/paired-bars",
      "interactiveImport": "@microcharts/react/paired-bars/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value, ref }[]",
      "primaryEncoding": "adjacent bar lengths, zero-anchored",
      "bestFor": [
        "budget vs actual per region",
        "target vs result rows"
      ],
      "avoidFor": [
        "no reference series (MiniBar)",
        "> 5 pairs"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; value; ref }[]",
          "required": true,
          "description": "Value + reference per category."
        },
        {
          "name": "mode",
          "type": "\"grouped\" | \"overlay\"",
          "required": false,
          "description": "Overlay puts the ref as a full-width ghost behind — halves the footprint."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Over/under-reference valence tint."
        },
        {
          "name": "orientation",
          "type": "\"horizontal\" | \"vertical\"",
          "required": false,
          "description": "Rows for wide cells."
        },
        {
          "name": "locale",
          "type": "string | string[]",
          "required": false,
          "description": "BCP 47 locale(s) for the gap named in the summary, e.g. \"de-DE\"."
        }
      ],
      "examples": [
        {
          "title": "Budget vs actual",
          "code": "import { PairedBars } from \"@microcharts/react/paired-bars\";\n\n<PairedBars data={regions} title=\"Actual vs plan\" />"
        }
      ]
    },
    {
      "name": "Slope",
      "slug": "slope",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/slope",
      "staticImport": "@microcharts/react/slope",
      "interactiveImport": "@microcharts/react/slope/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, from, to }[]",
      "primaryEncoding": "line slope between two aligned columns",
      "bestFor": [
        "before/after experiments",
        "rank shuffles",
        "two-moment comparisons"
      ],
      "avoidFor": [
        "the path between (Sparkline)",
        "> 7 categories"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; from; to }[]",
          "required": true,
          "description": "Two aligned moments per category."
        },
        {
          "name": "label",
          "type": "\"none\" | \"value\" | \"label\" | \"both\"",
          "required": false,
          "description": "End labels; dropped deterministically when rows collide."
        },
        {
          "name": "highlight",
          "type": "number | string",
          "required": false,
          "description": "The one-vs-field editorial read."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Direction valence; unset = neutral ink."
        }
      ],
      "examples": [
        {
          "title": "Before vs after",
          "code": "import { Slope } from \"@microcharts/react/slope\";\n\n<Slope data={cohorts} title=\"Before vs after\" />"
        }
      ]
    },
    {
      "name": "MicroScatter",
      "slug": "micro-scatter",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/micro-scatter",
      "staticImport": "@microcharts/react/micro-scatter",
      "interactiveImport": "@microcharts/react/micro-scatter/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ x, y }[] (unordered pairs)",
      "primaryEncoding": "2-D position on common scales",
      "bestFor": [
        "correlation in a sentence",
        "two-metric relationships in cards"
      ],
      "avoidFor": [
        "> 60 points (bin instead)",
        "time series (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ x; y }[]",
          "required": true,
          "description": "Unordered pairs."
        },
        {
          "name": "trend",
          "type": "boolean",
          "required": false,
          "description": "Least-squares line — linear only, never smoothed."
        },
        {
          "name": "focal",
          "type": "number",
          "required": false,
          "description": "Accent one point — \"this one, among all of them\"."
        },
        {
          "name": "xDomain",
          "type": "[number, number]",
          "required": false,
          "description": "X scale (domain keeps its grammar meaning: y)."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Y scale — the shared grammar name, paired with xDomain."
        },
        {
          "name": "r",
          "type": "number",
          "required": false,
          "description": "Dot radius, clamped [1, 3]."
        }
      ],
      "examples": [
        {
          "title": "Latency vs error rate",
          "code": "import { MicroScatter } from \"@microcharts/react/micro-scatter\";\n\n<MicroScatter data={pairs} title=\"Latency vs error rate\" />"
        }
      ]
    },
    {
      "name": "SegmentedBar",
      "slug": "segmented-bar",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/segmented-bar",
      "staticImport": "@microcharts/react/segmented-bar",
      "interactiveImport": "@microcharts/react/segmented-bar/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value }[] (parts of a whole)",
      "primaryEncoding": "segment length in a fixed bar",
      "bestFor": [
        "traffic mix per row",
        "composition in cards"
      ],
      "avoidFor": [
        "comparing across rows precisely (MiniBar)",
        "negative parts (Waterfall)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; value }[]",
          "required": true,
          "description": "Parts of the whole."
        },
        {
          "name": "maxSegments",
          "type": "number",
          "required": false,
          "description": "Rollup threshold — the tail becomes a labeled Other."
        },
        {
          "name": "order",
          "type": "\"data\" | \"desc\"",
          "required": false,
          "description": "Preserve inherent sequences or rank the composition."
        },
        {
          "name": "label",
          "type": "\"none\" | \"percent\" | \"value\"",
          "required": false,
          "description": "Centered per segment (deterministic drop-out; default percent)."
        },
        {
          "name": "colors",
          "type": "string[]",
          "required": false,
          "description": "Per-segment colours, cycled; overrides --mc-cat-N. Other stays neutral."
        }
      ],
      "examples": [
        {
          "title": "Browser share",
          "code": "import { SegmentedBar } from \"@microcharts/react/segmented-bar\";\n\n<SegmentedBar data={mix} title=\"Browser share\" />"
        }
      ]
    },
    {
      "name": "HistogramStrip",
      "slug": "histogram-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/histogram-strip",
      "staticImport": "@microcharts/react/histogram-strip",
      "interactiveImport": "@microcharts/react/histogram-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[] (raw observations, binned internally)",
      "primaryEncoding": "bar height per uniform bin",
      "bestFor": [
        "latency clusters in a sentence",
        "distributions per row"
      ],
      "avoidFor": [
        "pre-aggregated counts (SparkBar)",
        "raw marks (RugStrip)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Raw observations."
        },
        {
          "name": "bins",
          "type": "number",
          "required": false,
          "description": "Bin count; auto = min(12, √n)."
        },
        {
          "name": "markValue",
          "type": "number",
          "required": false,
          "description": "A VALUE whose bin gets accent."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Fixed bin edges across multiples."
        },
        {
          "name": "format",
          "type": "Intl.NumberFormatOptions | fn",
          "required": false,
          "description": "Formats the bin edges named in the summary."
        },
        {
          "name": "locale",
          "type": "string | string[]",
          "required": false,
          "description": "BCP 47 locale(s) for the formatted bin edges."
        }
      ],
      "examples": [
        {
          "title": "Response times",
          "code": "import { HistogramStrip } from \"@microcharts/react/histogram-strip\";\n\n<HistogramStrip data={times} title=\"Response times\" />"
        }
      ]
    },
    {
      "name": "MicroBox",
      "slug": "micro-box",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/micro-box",
      "staticImport": "@microcharts/react/micro-box",
      "interactiveImport": "@microcharts/react/micro-box/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[] OR { min, q1, median, q3, max }",
      "primaryEncoding": "box span (IQR) + median tick position",
      "bestFor": [
        "latency percentile rows",
        "spread beside a stat"
      ],
      "avoidFor": [
        "modality/shape (HistogramStrip)",
        "< 5 observations (renders dots)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": false,
          "description": "Raw observations (exclusive with stats)."
        },
        {
          "name": "stats",
          "type": "{ min; q1; median; q3; max }",
          "required": false,
          "description": "Precomputed server aggregates."
        },
        {
          "name": "whiskers",
          "type": "\"minmax\" | \"tukey\"",
          "required": false,
          "description": "Tukey exposes outliers as dots."
        },
        {
          "name": "outliers",
          "type": "boolean",
          "required": false,
          "description": "Render outlier dots in tukey mode."
        }
      ],
      "examples": [
        {
          "title": "Latency spread",
          "code": "import { MicroBox } from \"@microcharts/react/micro-box\";\n\n<MicroBox stats={{ min: 12, q1: 35, median: 42, q3: 51, max: 96 }} title=\"p95 latency\" />"
        }
      ]
    },
    {
      "name": "ProgressRing",
      "slug": "progress-ring",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/progress-ring",
      "staticImport": "@microcharts/react/progress-ring",
      "interactiveImport": "@microcharts/react/progress-ring/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onSelect"
      ],
      "dataShape": "value of max",
      "primaryEncoding": "arc sweep (fixed 12-o'clock start)",
      "bestFor": [
        "tab headers",
        "KPI card corners",
        "cooldowns (sweep)"
      ],
      "avoidFor": [
        "precise reads (Progress)",
        "gauges (never shipped)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The progressed amount."
        },
        {
          "name": "max",
          "type": "number",
          "required": false,
          "description": "Denominator (default 1)."
        },
        {
          "name": "sweep",
          "type": "boolean",
          "required": false,
          "description": "Countdown: the REMAINING wedge shrinks."
        },
        {
          "name": "weight",
          "type": "number",
          "required": false,
          "description": "Ring thickness (viewBox units)."
        },
        {
          "name": "label",
          "type": "\"none\" | \"percent\"",
          "required": false,
          "description": "Centered figure (≥ 20 px rendered)."
        }
      ],
      "examples": [
        {
          "title": "Backup",
          "code": "import { ProgressRing } from \"@microcharts/react/progress-ring\";\n\n<ProgressRing value={0.68} title=\"Backup\" />"
        }
      ]
    },
    {
      "name": "MicroDonut",
      "slug": "micro-donut",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/micro-donut",
      "staticImport": "@microcharts/react/micro-donut",
      "interactiveImport": "@microcharts/react/micro-donut/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value }[]",
      "primaryEncoding": "wedge angle",
      "bestFor": [
        "mix icon beside a printed number",
        "KPI card corners"
      ],
      "avoidFor": [
        "comparative reads (SegmentedBar)",
        "precision of any kind"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; value }[]",
          "required": true,
          "description": "Parts of the whole."
        },
        {
          "name": "maxWedges",
          "type": "number",
          "required": false,
          "description": "Rollup threshold (default 4)."
        },
        {
          "name": "decorative",
          "type": "boolean",
          "required": false,
          "description": "Redundant ornament beside a printed value → aria-hidden."
        },
        {
          "name": "weight",
          "type": "number",
          "required": false,
          "description": "Annulus thickness (shared with ProgressRing)."
        },
        {
          "name": "label",
          "type": "\"none\" | \"total\"",
          "required": false,
          "description": "Center total when the hole has room (default \"none\")."
        },
        {
          "name": "colors",
          "type": "string[]",
          "required": false,
          "description": "Per-wedge colours, cycled; overrides --mc-cat-N. Other stays neutral."
        }
      ],
      "examples": [
        {
          "title": "Traffic mix",
          "code": "import { MicroDonut } from \"@microcharts/react/micro-donut\";\n\n<MicroDonut data={mix} title=\"Traffic mix\" />"
        }
      ]
    },
    {
      "name": "Funnel",
      "slug": "funnel",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/funnel",
      "staticImport": "@microcharts/react/funnel",
      "interactiveImport": "@microcharts/react/funnel/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value }[] (ordered stages)",
      "primaryEncoding": "column height per stage, zero-anchored",
      "bestFor": [
        "per-campaign funnels in tables",
        "conversion in cards"
      ],
      "avoidFor": [
        "unordered categories (MiniBar)",
        "> 6 stages"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; value }[]",
          "required": true,
          "description": "Ordered stages."
        },
        {
          "name": "mode",
          "type": "\"absolute\" | \"rate\"",
          "required": false,
          "description": "Rate = % of the FIRST stage (never the previous)."
        },
        {
          "name": "connectors",
          "type": "boolean",
          "required": false,
          "description": "Retained-share slats between stages."
        },
        {
          "name": "label",
          "type": "\"none\" | \"percent\" | \"value\"",
          "required": false,
          "description": "Above each column (deterministic drop-out; default percent)."
        },
        {
          "name": "highlight",
          "type": "number | string",
          "required": false,
          "description": "Accent the leak stage."
        }
      ],
      "examples": [
        {
          "title": "Signup funnel",
          "code": "import { Funnel } from \"@microcharts/react/funnel\";\n\n<Funnel data={stages} title=\"Signup funnel\" />"
        }
      ]
    },
    {
      "name": "LikertStrip",
      "slug": "likert-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/likert-strip",
      "staticImport": "@microcharts/react/likert-strip",
      "interactiveImport": "@microcharts/react/likert-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value }[] ordered most-negative → most-positive (2–7 levels)",
      "primaryEncoding": "signed segment length from a center line",
      "bestFor": [
        "survey question rows (SparkGroup shared scale)",
        "sentiment in cards"
      ],
      "avoidFor": [
        "> 7 levels",
        "unvalenced composition (SegmentedBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; value }[]",
          "required": true,
          "description": "Ordinal levels, negative → positive."
        },
        {
          "name": "neutral",
          "type": "\"split\" | \"omit\"",
          "required": false,
          "description": "Center-straddle or omit-from-bar (always labeled)."
        },
        {
          "name": "label",
          "type": "\"ends\" | \"net\" | \"none\"",
          "required": false,
          "description": "Agree/disagree % or one signed score."
        }
      ],
      "examples": [
        {
          "title": "Q1 satisfaction",
          "code": "import { LikertStrip } from \"@microcharts/react/likert-strip\";\n\n<LikertStrip\n  data={[\n    { label: \"Strongly disagree\", value: 10 },\n    { label: \"Disagree\", value: 14 },\n    { label: \"Neutral\", value: 14 },\n    { label: \"Agree\", value: 34 },\n    { label: \"Strongly agree\", value: 28 },\n  ]}\n  title=\"Q1 satisfaction\"\n/>"
        }
      ]
    },
    {
      "name": "Waterfall",
      "slug": "waterfall",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/waterfall",
      "staticImport": "@microcharts/react/waterfall",
      "interactiveImport": "@microcharts/react/waterfall/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value }[] of signed deltas, in order",
      "primaryEncoding": "bar position/length from a running level",
      "bestFor": [
        "P&L bridges in table cells",
        "net-change decomposition in KPI cards"
      ],
      "avoidFor": [
        "unordered category comparison (MiniBar)",
        "more than ~8 steps"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; value }[]",
          "required": true,
          "description": "Signed deltas in order."
        },
        {
          "name": "open",
          "type": "number",
          "required": false,
          "description": "Opening level (prior-period close)."
        },
        {
          "name": "totalBar",
          "type": "boolean",
          "required": false,
          "description": "Zero-anchored closing total bar (default on)."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "\"down\" = decreases are good (cost breakdowns)."
        },
        {
          "name": "label",
          "type": "\"none\" | \"delta\"",
          "required": false,
          "description": "\"delta\" (default) prints each step's signed value in a band below the plot; the biggest movers win when labels would collide."
        }
      ],
      "examples": [
        {
          "title": "Net income bridge",
          "code": "import { Waterfall } from \"@microcharts/react/waterfall\";\n\n<Waterfall data={steps} open={60} title=\"Net income bridge\" />"
        }
      ]
    },
    {
      "name": "BumpStrip",
      "slug": "bump-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/bump-strip",
      "staticImport": "@microcharts/react/bump-strip",
      "interactiveImport": "@microcharts/react/bump-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(number | null)[] of 1-based ranks per period (null = unranked)",
      "primaryEncoding": "vertical position on an inverted rank scale (#1 on top)",
      "bestFor": [
        "leaderboard rows",
        "category-rank trends in KPI cards"
      ],
      "avoidFor": [
        "continuous values (Sparkline)",
        "more than ~15 rank levels"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "1-based integer ranks; null = unranked period (gap)."
        },
        {
          "name": "maxRank",
          "type": "number",
          "required": false,
          "description": "Fix the band so small multiples share a rank scale."
        },
        {
          "name": "dots",
          "type": "\"changes\" | \"none\"",
          "required": false,
          "description": "Mark the moments rank actually moved."
        },
        {
          "name": "label",
          "type": "\"ends\" | \"last\" | \"none\"",
          "required": false,
          "description": "\"#5\" → \"#1\" endpoint labels."
        }
      ],
      "examples": [
        {
          "title": "Category rank",
          "code": "import { BumpStrip } from \"@microcharts/react/bump-strip\";\n\n<BumpStrip data={weeklyRanks} title=\"Category rank\" />"
        }
      ]
    },
    {
      "name": "DualSparkline",
      "slug": "dual-sparkline",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/dual-sparkline",
      "staticImport": "@microcharts/react/dual-sparkline",
      "interactiveImport": "@microcharts/react/dual-sparkline/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "data: (number | null)[] + compare: (number | null)[], exactly two series",
      "primaryEncoding": "two line positions on ONE shared scale",
      "bestFor": [
        "metric-vs-benchmark in table cells",
        "actual-vs-plan in KPI cards"
      ],
      "avoidFor": [
        "3+ series (SparkGroup)",
        "different units per series (never dual axes)"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "The series being judged."
        },
        {
          "name": "compare",
          "type": "(number | null)[]",
          "required": true,
          "description": "The benchmark — dashed, thinner, neutral."
        },
        {
          "name": "curve",
          "type": "\"linear\" | \"smooth\" | \"step\"",
          "required": false,
          "description": "Line shape (default 'linear')."
        },
        {
          "name": "band",
          "type": "[number, number]",
          "required": false,
          "description": "Normal-range band behind both (shared grammar)."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Endpoint value label for the primary series."
        },
        {
          "name": "dots",
          "type": "\"auto\" | \"none\"",
          "required": false,
          "description": "Endpoint dots on both lines (default \"auto\")."
        },
        {
          "name": "seriesStrings",
          "type": "SeriesStrings",
          "required": false,
          "description": "i18n strings for the per-series trend clauses."
        }
      ],
      "examples": [
        {
          "title": "Conversion vs market",
          "code": "import { DualSparkline } from \"@microcharts/react/dual-sparkline\";\n\n<DualSparkline data={ours} compare={market} title=\"Conversion vs market\" />"
        }
      ]
    },
    {
      "name": "StackedArea",
      "slug": "stacked-area",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/stacked-area",
      "staticImport": "@microcharts/react/stacked-area",
      "interactiveImport": "@microcharts/react/stacked-area/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, values }[], at most 3 series, stacked to 100%",
      "primaryEncoding": "layer thickness (share) over time",
      "bestFor": [
        "traffic/revenue mix in KPI cards",
        "share-shift stories in sentences"
      ],
      "avoidFor": [
        "4+ series",
        "exact values over time (SparkGroup of Sparklines)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; values }[]",
          "required": true,
          "description": "≤ 3 series (hard cap)."
        },
        {
          "name": "mode",
          "type": "\"stacked\" | \"ridge\"",
          "required": false,
          "description": "Ridge = same stack, overlapping-crest skin."
        },
        {
          "name": "order",
          "type": "\"data\" | \"asc\"",
          "required": false,
          "description": "\"asc\" puts the smallest series on top (least distortion)."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Endpoint share labels per series (deterministic drop-out)."
        },
        {
          "name": "labelAt",
          "type": "number",
          "required": false,
          "description": "Column whose shares feed label=\"last\" (default: final column). The interactive entry passes the focused column so the labels track the crosshair."
        },
        {
          "name": "curve",
          "type": "\"linear\" | \"smooth\" | \"step\"",
          "required": false,
          "description": "Line interpolation (default linear); ridge forces smooth."
        },
        {
          "name": "colors",
          "type": "string[]",
          "required": false,
          "description": "Per-series colours, cycled; overrides --mc-cat-N."
        }
      ],
      "examples": [
        {
          "title": "Traffic mix",
          "code": "import { StackedArea } from \"@microcharts/react/stacked-area\";\n\n<StackedArea data={mix} title=\"Traffic mix\" />"
        }
      ]
    },
    {
      "name": "Ohlc",
      "slug": "ohlc",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/ohlc",
      "staticImport": "@microcharts/react/ohlc",
      "interactiveImport": "@microcharts/react/ohlc/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ open, high, low, close }[] per period, oldest first",
      "primaryEncoding": "candle body span + wick extent on a shared price scale",
      "bestFor": [
        "watchlist table rows",
        "ticker KPI cards"
      ],
      "avoidFor": [
        "a single close series (Sparkline)",
        "more than ~20 periods"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ open; high; low; close }[]",
          "required": true,
          "description": "Periods, oldest first."
        },
        {
          "name": "mode",
          "type": "\"candle\" | \"bars\"",
          "required": false,
          "description": "Candle bodies or open/close ticks."
        },
        {
          "name": "maxPeriods",
          "type": "number",
          "required": false,
          "description": "Renders the most recent N (never averaged)."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Last close in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "ACME sessions",
          "code": "import { Ohlc } from \"@microcharts/react/ohlc\";\n\n<Ohlc data={sessions} title=\"ACME sessions\" />"
        }
      ]
    },
    {
      "name": "Horizon",
      "slug": "horizon",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/horizon",
      "staticImport": "@microcharts/react/horizon",
      "interactiveImport": "@microcharts/react/horizon/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(number | null)[] over time",
      "primaryEncoding": "position + fold-layer opacity (darker = higher band)",
      "bestFor": [
        "dense monitoring rows (dozens stacked)",
        "wide-range series in tight cells"
      ],
      "avoidFor": [
        "first-glance audiences (folding needs a key)",
        "few rows with room (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "Series over time."
        },
        {
          "name": "folds",
          "type": "2 | 3",
          "required": false,
          "description": "Band count — 3 only when the range genuinely spans it."
        },
        {
          "name": "mode",
          "type": "\"mirror\" | \"offset\"",
          "required": false,
          "description": "Mirror flips negatives upward (denser); offset keeps up/down."
        },
        {
          "name": "baseline",
          "type": "number",
          "required": false,
          "description": "Fold origin (e.g. a target level) — authored, never inferred."
        }
      ],
      "examples": [
        {
          "title": "Cluster load",
          "code": "import { Horizon } from \"@microcharts/react/horizon\";\n\n<Horizon data={cpuLoad} title=\"Cluster load\" />"
        }
      ]
    },
    {
      "name": "CalendarStrip",
      "slug": "calendar-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/calendar-strip",
      "staticImport": "@microcharts/react/calendar-strip",
      "interactiveImport": "@microcharts/react/calendar-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ date: ISO string | Date, value }[], date-indexed, not slot-indexed",
      "primaryEncoding": "discrete color step per real calendar day",
      "bestFor": [
        "habit/deploy cadence in KPI cards",
        "week-aligned recent activity"
      ],
      "avoidFor": [
        "long ordinal histories (ActivityGrid)",
        "exact per-day values (MiniBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ date; value }[]",
          "required": true,
          "description": "Date-keyed values; duplicates sum with a dev warning."
        },
        {
          "name": "weeks",
          "type": "number",
          "required": false,
          "description": "Window length in whole weeks ending at `end` (default 4)."
        },
        {
          "name": "end",
          "type": "string | Date",
          "required": false,
          "description": "Last day of the window (defaults to today UTC — pin it for SSR determinism)."
        },
        {
          "name": "weekStart",
          "type": "0 | 1",
          "required": false,
          "description": "Locale start-of-week (default Monday)."
        },
        {
          "name": "steps",
          "type": "number",
          "required": false,
          "description": "Intensity steps including the zero track (default 5)."
        },
        {
          "name": "shape",
          "type": "\"square\" | \"round\" | \"dot\"",
          "required": false,
          "description": "Shared cell vocabulary."
        },
        {
          "name": "cell",
          "type": "number",
          "required": false,
          "description": "Cell edge length in viewBox units (default 7)."
        },
        {
          "name": "gap",
          "type": "number",
          "required": false,
          "description": "Gap between cells (default 1)."
        },
        {
          "name": "dateFormat",
          "type": "Intl.DateTimeFormatOptions | (d: Date) => string",
          "required": false,
          "description": "Announced day label (defaults to weekday + month + day, UTC).",
          "interactive": true
        }
      ],
      "examples": [
        {
          "title": "Deploy cadence",
          "code": "import { CalendarStrip } from \"@microcharts/react/calendar-strip\";\n\n<CalendarStrip data={days} end=\"2026-07-01\" title=\"Deploy cadence\" />"
        }
      ]
    },
    {
      "name": "EventTimeline",
      "slug": "event-timeline",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/event-timeline",
      "staticImport": "@microcharts/react/event-timeline",
      "interactiveImport": "@microcharts/react/event-timeline/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ start, end?, label?, kind? }[], end present = span, absent = point event",
      "primaryEncoding": "span extent on a linear time axis; points as position marks",
      "bestFor": [
        "per-service uptime rows",
        "on-call shifts and release windows in cards"
      ],
      "avoidFor": [
        "more than ~12 items",
        "aggregated durations (MiniBar of totals)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ start; end?; label?; kind? }[]",
          "required": true,
          "description": "Spans (with end) and point events (without), ms epoch or Date."
        },
        {
          "name": "domain",
          "type": "[start, end]",
          "required": false,
          "description": "The window — fix it across rows for small multiples."
        },
        {
          "name": "now",
          "type": "number | Date",
          "required": false,
          "description": "Current-moment tick; authored, never implicit."
        },
        {
          "name": "label",
          "type": "\"none\" | \"spans\"",
          "required": false,
          "description": "Centered in-span labels with deterministic drop-out."
        },
        {
          "name": "dateFormat",
          "type": "Intl.DateTimeFormatOptions | (d: Date) => string",
          "required": false,
          "description": "Announced timestamp format for focused events (defaults to a locale date-time).",
          "interactive": true
        }
      ],
      "examples": [
        {
          "title": "API uptime",
          "code": "import { EventTimeline } from \"@microcharts/react/event-timeline\";\n\n<EventTimeline data={windows} domain={today} title=\"API uptime\" />"
        }
      ]
    },
    {
      "name": "CoverageStrip",
      "slug": "coverage-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/coverage-strip",
      "staticImport": "@microcharts/react/coverage-strip",
      "interactiveImport": "@microcharts/react/coverage-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(number | null)[]",
      "primaryEncoding": "presence/absence as cell fill on a time strip",
      "bestFor": [
        "data-quality cells beside a metric",
        "sensor uptime rows",
        "trailing-gap detection"
      ],
      "avoidFor": [
        "magnitude over time (HeatStrip)",
        "exact values (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "Time-ordered slots; null = no measurement, 0 = a measured zero."
        },
        {
          "name": "expected",
          "type": "number",
          "required": false,
          "description": "Slots the window should contain — lets trailing missingness count."
        },
        {
          "name": "mode",
          "type": "\"binary\" | \"intensity\"",
          "required": false,
          "description": "Presence only (default), or shade measured cells by value."
        },
        {
          "name": "steps",
          "type": "number",
          "required": false,
          "description": "Intensity granularity (default 5)."
        },
        {
          "name": "shape",
          "type": "\"square\" | \"round\" | \"dot\"",
          "required": false,
          "description": "Cell shape from the shared vocabulary (default 'square')."
        },
        {
          "name": "label",
          "type": "\"percent\" | \"none\"",
          "required": false,
          "description": "State the coverage number in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "Sensor uptime",
          "code": "import { CoverageStrip } from \"@microcharts/react/coverage-strip\";\n\n<CoverageStrip data={readings} expected={18} label=\"percent\" title=\"Sensor uptime\" />"
        }
      ]
    },
    {
      "name": "BenchmarkStrip",
      "slug": "benchmark-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/benchmark-strip",
      "staticImport": "@microcharts/react/benchmark-strip",
      "interactiveImport": "@microcharts/react/benchmark-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[] + value",
      "primaryEncoding": "position on a common scale against an empirical band",
      "bestFor": [
        "a value against its cohort",
        "per-row peer comparison in tables",
        "SLA context"
      ],
      "avoidFor": [
        "a single trend (Sparkline)",
        "two groups (ABStrips)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Peer values."
        },
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The focal reading."
        },
        {
          "name": "range",
          "type": "\"p5p95\" | \"minmax\"",
          "required": false,
          "description": "Outer band; minmax for small samples."
        },
        {
          "name": "label",
          "type": "\"value\" | \"percentile\" | \"none\"",
          "required": false,
          "description": "What the right gutter states (default percentile)."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Which side of the band is good (colors the focal dot)."
        },
        {
          "name": "median",
          "type": "boolean",
          "required": false,
          "description": "Center tick (default true)."
        }
      ],
      "examples": [
        {
          "title": "Latency vs peers",
          "code": "import { BenchmarkStrip } from \"@microcharts/react/benchmark-strip\";\n\n<BenchmarkStrip data={peerLatencies} value={312} format={{ style: \"unit\", unit: \"millisecond\" }} title=\"Latency vs peers\" />"
        }
      ]
    },
    {
      "name": "PercentileLadder",
      "slug": "percentile-ladder",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/percentile-ladder",
      "staticImport": "@microcharts/react/percentile-ladder",
      "interactiveImport": "@microcharts/react/percentile-ladder/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[]",
      "primaryEncoding": "tick position on a zero-anchored strip",
      "bestFor": [
        "latency SLOs in a sentence",
        "tail per endpoint in tables",
        "payment-size spread"
      ],
      "avoidFor": [
        "odds of an outcome (QuantileDots)",
        "full shape (MicroBox)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Raw sample; quantiles are derived."
        },
        {
          "name": "ps",
          "type": "number[]",
          "required": false,
          "description": "Percentiles to mark (default [50, 90, 99], 2–4)."
        },
        {
          "name": "scale",
          "type": "\"linear\" | \"log\"",
          "required": false,
          "description": "Log for long tails (falls back on any value ≤ 0; renders a log tag)."
        },
        {
          "name": "label",
          "type": "\"ps\" | \"values\" | \"both\" | \"none\"",
          "required": false,
          "description": "What the tick labels state."
        },
        {
          "name": "marks",
          "type": "\"tick\" | \"dot\"",
          "required": false,
          "description": "Tick marks (default) or dot marks — dots read calmer over dense text."
        }
      ],
      "examples": [
        {
          "title": "Request latency",
          "code": "import { PercentileLadder } from \"@microcharts/react/percentile-ladder\";\n\n<PercentileLadder\n  data={Array.from({ length: 200 }, (_, i) =>\n    i < 130\n      ? 90 + (i % 50)\n      : i < 180\n        ? 150 + ((i * 7) % 320)\n        : i < 196\n          ? 480 + ((i * 11) % 900)\n          : 1500 + ((i * 13) % 800),\n  )}\n  format={{ style: \"unit\", unit: \"millisecond\" }}\n  title=\"Request latency\"\n/>"
        }
      ]
    },
    {
      "name": "GradedBand",
      "slug": "graded-band",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/graded-band",
      "staticImport": "@microcharts/react/graded-band",
      "interactiveImport": "@microcharts/react/graded-band/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[]",
      "primaryEncoding": "nested interval extent, graded by opacity",
      "bestFor": [
        "a forecast with its uncertainty",
        "estimate-vs-actual in a KPI card",
        "posterior summaries"
      ],
      "avoidFor": [
        "countable odds (QuantileDots)",
        "a forecast over time (ForecastCone)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Sample / posterior draws; the component derives the intervals."
        },
        {
          "name": "levels",
          "type": "number[]",
          "required": false,
          "description": "1–3 nested central intervals (default [50, 80, 95])."
        },
        {
          "name": "value",
          "type": "number",
          "required": false,
          "description": "Observed value overlaid as a dot."
        },
        {
          "name": "softEdge",
          "type": "boolean",
          "required": false,
          "description": "Fade past the outer band — 'this is approximate'."
        },
        {
          "name": "label",
          "type": "\"median\" | \"none\"",
          "required": false,
          "description": "States the median in a right gutter (default none)."
        }
      ],
      "examples": [
        {
          "title": "Forecast estimate",
          "code": "import { GradedBand } from \"@microcharts/react/graded-band\";\n\n<GradedBand data={posterior} label=\"median\" title=\"Forecast estimate\" />"
        }
      ]
    },
    {
      "name": "IconArray",
      "slug": "icon-array",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/icon-array",
      "staticImport": "@microcharts/react/icon-array",
      "interactiveImport": "@microcharts/react/icon-array/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex"
      ],
      "dataShape": "value (0–1)",
      "primaryEncoding": "count of filled units in a fixed N-unit grid",
      "bestFor": [
        "risk in a sentence",
        "uptake / adoption rates",
        "lay-audience probabilities"
      ],
      "avoidFor": [
        "a trend (Sparkline)",
        "a distribution (QuantileDots)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The rate, 0–1."
        },
        {
          "name": "total",
          "type": "10 | 20 | 100",
          "required": false,
          "description": "Denominator / grid size (default 20)."
        },
        {
          "name": "label",
          "type": "\"ratio\" | \"percent\" | \"none\"",
          "required": false,
          "description": "\"3 in 20\" (default) reads better than \"15%\" for lay audiences."
        },
        {
          "name": "shape",
          "type": "\"square\" | \"round\" | \"dot\"",
          "required": false,
          "description": "Shared cell vocabulary (default square)."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Polarity — down (fewer is better) flips the fill to the risk tone."
        }
      ],
      "examples": [
        {
          "title": "Adverse events",
          "code": "import { IconArray } from \"@microcharts/react/icon-array\";\n\n<IconArray value={0.15} total={20} title=\"Adverse events\" />"
        }
      ]
    },
    {
      "name": "RateVolume",
      "slug": "rate-volume",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/rate-volume",
      "staticImport": "@microcharts/react/rate-volume",
      "interactiveImport": "@microcharts/react/rate-volume/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ rate, volume }[] per period, oldest first",
      "primaryEncoding": "line position (rate) over zero-anchored ghost bars (volume)",
      "bestFor": [
        "a conversion / error rate with its denominator",
        "a KPI card where the rate is the headline",
        "spotting a big rate move on thin volume"
      ],
      "avoidFor": [
        "volume itself needing a precise read (pair a SparkBar)",
        "a plain series (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ rate; volume }[]",
          "required": true,
          "description": "Periods, oldest first — each a rate and the volume it was measured on."
        },
        {
          "name": "minVolume",
          "type": "number",
          "required": false,
          "description": "Below it, the rate mark renders hollow — 'insufficient denominator'."
        },
        {
          "name": "curve",
          "type": "\"linear\" | \"step\"",
          "required": false,
          "description": "Step suits per-period aggregate rates."
        },
        {
          "name": "volumeFormat",
          "type": "Intl.NumberFormatOptions | (n) => string",
          "required": false,
          "description": "Volume has different units than rate; formatted separately."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Noun for the volume unit in the summary (default 'events')."
        },
        {
          "name": "volumeDomain",
          "type": "[number, number]",
          "required": false,
          "description": "Volume (bar) domain — defaults to [0, max], zero-anchored."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Endpoint rate in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "Conversion rate",
          "code": "import { RateVolume } from \"@microcharts/react/rate-volume\";\n\n<RateVolume data={periods} minVolume={50} title=\"Conversion rate\" />"
        }
      ]
    },
    {
      "name": "NetFlow",
      "slug": "net-flow",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/net-flow",
      "staticImport": "@microcharts/react/net-flow",
      "interactiveImport": "@microcharts/react/net-flow/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ in, out }[] per period, oldest first",
      "primaryEncoding": "mirrored area extent around zero + net line position",
      "bestFor": [
        "cash flow per account row",
        "user in/out (signups vs churn) in a KPI card",
        "any in-vs-out where the net is the decision"
      ],
      "avoidFor": [
        "a single net series (Sparkline)",
        "one period's split (Delta / SegmentedBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ in; out }[]",
          "required": true,
          "description": "Periods, oldest first — inflow and outflow magnitudes (both ≥ 0)."
        },
        {
          "name": "mode",
          "type": "\"area\" | \"bars\"",
          "required": false,
          "description": "Mirrored areas (default) or discrete columns for few periods."
        },
        {
          "name": "net",
          "type": "boolean",
          "required": false,
          "description": "The net line (in − out). Default true."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Which direction is good — 'down' for debt-paydown contexts."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Signed net in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "Monthly cash flow",
          "code": "import { NetFlow } from \"@microcharts/react/net-flow\";\n\n<NetFlow data={months} title=\"Monthly cash flow\" />"
        }
      ]
    },
    {
      "name": "RetentionCurve",
      "slug": "retention-curve",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/retention-curve",
      "staticImport": "@microcharts/react/retention-curve",
      "interactiveImport": "@microcharts/react/retention-curve/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[], fraction retained per period (period 0 ≈ 1.0)",
      "primaryEncoding": "step-line position on a locked [0,1] scale",
      "bestFor": [
        "a cohort retention curve in a KPI card",
        "your decay vs an industry benchmark",
        "spotting whether retention plateaus (or keeps leaking)"
      ],
      "avoidFor": [
        "a continuous signal (Sparkline)",
        "one-number retention (Progress / Delta)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Fraction retained per period (0–1 or 0–100); period 0 is typically 1.0."
        },
        {
          "name": "benchmark",
          "type": "number[]",
          "required": false,
          "description": "Peer/industry curve, drawn as a subordinate dashed ghost."
        },
        {
          "name": "plateau",
          "type": "boolean",
          "required": false,
          "description": "Detect + mark a plateau (default true)."
        },
        {
          "name": "curve",
          "type": "\"step\" | \"smooth\"",
          "required": false,
          "description": "Step (default — cohorts are discrete) or smooth (editorial)."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Period noun for the summary (default 'period')."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Final retention in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "W12 cohort",
          "code": "import { RetentionCurve } from \"@microcharts/react/retention-curve\";\n\n<RetentionCurve data={cohort} unit=\"week\" title=\"W12 cohort\" />"
        }
      ]
    },
    {
      "name": "BurnChart",
      "slug": "burn-chart",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/burn-chart",
      "staticImport": "@microcharts/react/burn-chart",
      "interactiveImport": "@microcharts/react/burn-chart/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ plan: number[]; actual: number[] }, remaining work per period",
      "primaryEncoding": "actual line vs the plan line + projected landing gap",
      "bestFor": [
        "a sprint burndown in a tab header",
        "will-we-finish in a KPI card",
        "plan vs actual with a projected landing"
      ],
      "avoidFor": [
        "a single progress number (Progress)",
        "a plain series (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ plan: number[]; actual: number[] }",
          "required": true,
          "description": "Remaining work per period (mode='down') or completed (mode='up')."
        },
        {
          "name": "mode",
          "type": "\"down\" | \"up\"",
          "required": false,
          "description": "Burn-down (remaining → 0, default) or burn-up (done → scope)."
        },
        {
          "name": "projection",
          "type": "boolean",
          "required": false,
          "description": "The dotted extrapolation to the deadline (default true)."
        },
        {
          "name": "work",
          "type": "string",
          "required": false,
          "description": "Work-unit noun for the summary and readout. Defaults to `strings.burnWork` ('points' in EN), so a localized bundle replaces it."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Period noun for the summary and gap label (default 'day')."
        },
        {
          "name": "label",
          "type": "\"gap\" | \"none\"",
          "required": false,
          "description": "Signed schedule landing vs the deadline in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "Sprint 12",
          "code": "import { BurnChart } from \"@microcharts/react/burn-chart\";\n\n<BurnChart data={{ plan, actual }} title=\"Sprint 12\" />"
        }
      ]
    },
    {
      "name": "ErrorBudget",
      "slug": "error-budget",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/error-budget",
      "staticImport": "@microcharts/react/error-budget",
      "interactiveImport": "@microcharts/react/error-budget/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[], budget remaining (0–1) per elapsed step; index 0 = 1.0",
      "primaryEncoding": "remaining-line position vs the steady-burn diagonal",
      "bestFor": [
        "an SLO error budget in a KPI card",
        "a service list where each row is a budget",
        "spotting a fast-burn before it exhausts the window"
      ],
      "avoidFor": [
        "a plain uptime series (Sparkline)",
        "one-number budget (Progress)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Budget remaining (0–1) per elapsed step; index 0 is 1.0."
        },
        {
          "name": "window",
          "type": "number",
          "required": false,
          "description": "Total steps in the SLO window (default = data.length)."
        },
        {
          "name": "rates",
          "type": "number[]",
          "required": false,
          "description": "Burn-rate reference multiples (default the SRE 1×/6×/14.4× convention)."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Period noun for the summary (default \"day\")."
        },
        {
          "name": "label",
          "type": "\"remaining\" | \"none\"",
          "required": false,
          "description": "Current budget % in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "Checkout SLO",
          "code": "import { ErrorBudget } from \"@microcharts/react/error-budget\";\n\n<ErrorBudget data={remaining} window={30} title=\"Checkout SLO\" />"
        }
      ]
    },
    {
      "name": "ControlStrip",
      "slug": "control-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/control-strip",
      "staticImport": "@microcharts/react/control-strip",
      "interactiveImport": "@microcharts/react/control-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[], sequential process measurements",
      "primaryEncoding": "point position vs the ±3σ̂ control band",
      "bestFor": [
        "a production line / metric in a table cell",
        "an SPC control chart in a KPI card",
        "flagging out-of-control excursions at a glance"
      ],
      "avoidFor": [
        "a plain trend (Sparkline)",
        "a strongly trending series (ChangePoint)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Sequential measurements."
        },
        {
          "name": "limits",
          "type": "\"sigma\" | \"percentile\"",
          "required": false,
          "description": "±3σ̂ (default) or empirical p0.135/p99.865 for skewed processes."
        },
        {
          "name": "baseline",
          "type": "number",
          "required": false,
          "description": "Known process center from a reference period (else = mean)."
        },
        {
          "name": "rules",
          "type": "\"none\" | \"we\"",
          "required": false,
          "description": "Western Electric secondary run rules (WE-1/2/4 subset)."
        },
        {
          "name": "dots",
          "type": "\"out\" | \"all\" | \"none\"",
          "required": false,
          "description": "Mark only out-of-control points (default), every point, or none."
        }
      ],
      "examples": [
        {
          "title": "Line 3 fill weight",
          "code": "import { ControlStrip } from \"@microcharts/react/control-strip\";\n\n<ControlStrip data={weights} title=\"Line 3 fill weight\" />"
        }
      ]
    },
    {
      "name": "ForecastCone",
      "slug": "forecast-cone",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/forecast-cone",
      "staticImport": "@microcharts/react/forecast-cone",
      "interactiveImport": "@microcharts/react/forecast-cone/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[] history + { mid, p80, p50? } forecast",
      "primaryEncoding": "prediction-band extent widening over the horizon",
      "bestFor": [
        "a \"will we hit Q4?\" forecast in a KPI card",
        "a projection with honest uncertainty in a sentence",
        "band-vs-target landing reads"
      ],
      "avoidFor": [
        "a forecast with no uncertainty (Sparkline)",
        "one estimate's spread (GradedBand)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Historical actuals."
        },
        {
          "name": "forecast",
          "type": "{ mid: number[]; p80: [lo,hi][]; p50?: [lo,hi][] }",
          "required": true,
          "description": "Median + prediction bands (at most 2: 50/80)."
        },
        {
          "name": "target",
          "type": "number",
          "required": false,
          "description": "The landing reference the cone must clear (adds a clearance clause)."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Period noun for the summary (default \"week\")."
        },
        {
          "name": "label",
          "type": "\"landing\" | \"none\"",
          "required": false,
          "description": "Median endpoint value in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "Q4 revenue",
          "code": "import { ForecastCone } from \"@microcharts/react/forecast-cone\";\n\n<ForecastCone data={history} forecast={forecast} target={45} title=\"Q4 revenue\" />"
        }
      ]
    },
    {
      "name": "QuantileDots",
      "slug": "quantile-dots",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/quantile-dots",
      "staticImport": "@microcharts/react/quantile-dots",
      "interactiveImport": "@microcharts/react/quantile-dots/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[], raw sample or posterior draws",
      "primaryEncoding": "countable dot frequency past a threshold",
      "bestFor": [
        "a \"will we miss the SLA?\" read in a sentence",
        "odds you can count in a KPI card",
        "a posterior you want to communicate as frequency, not percent"
      ],
      "avoidFor": [
        "a precise distribution shape (HistogramStrip)",
        "one estimate's interval (GradedBand)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Raw sample or posterior draws — the component derives the quantile dots."
        },
        {
          "name": "count",
          "type": "number",
          "required": false,
          "description": "Number of quantile dots (default 20; 15–20 recommended; capped at 25)."
        },
        {
          "name": "threshold",
          "type": "number",
          "required": false,
          "description": "The decision line — turns the plot from shape into odds."
        },
        {
          "name": "side",
          "type": "\"above\" | \"below\"",
          "required": false,
          "description": "Which side of the threshold is the event being counted."
        }
      ],
      "examples": [
        {
          "title": "Bus wait",
          "code": "import { QuantileDots } from \"@microcharts/react/quantile-dots\";\n\n<QuantileDots data={waits} threshold={15} format={(n) => `${n} min`} title=\"Bus wait\" />"
        }
      ]
    },
    {
      "name": "ABStrips",
      "slug": "ab-strips",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/ab-strips",
      "staticImport": "@microcharts/react/ab-strips",
      "interactiveImport": "@microcharts/react/ab-strips/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ a: number[]; b: number[] }, the two arms",
      "primaryEncoding": "two graded quantile strips on one scale; the overlap is the answer",
      "bestFor": [
        "an A/B experiment result in a KPI card",
        "control vs test in an experiments table",
        "any two-sample comparison where the spread matters"
      ],
      "avoidFor": [
        "a single distribution (BenchmarkStrip)",
        "more than two arms (small multiples)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ a: number[]; b: number[] }",
          "required": true,
          "description": "The two arms — raw samples, not summaries."
        },
        {
          "name": "seriesLabels",
          "type": "[string, string]",
          "required": false,
          "description": "Row identities for the gutter tags + summary (default ['A', 'B'])."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Which direction of the B−A delta reads as good (colors the delta)."
        },
        {
          "name": "label",
          "type": "\"delta\" | \"none\"",
          "required": false,
          "description": "Signed median delta in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "Latency A/B",
          "code": "import { ABStrips } from \"@microcharts/react/ab-strips\";\n\nconst control = Array.from({ length: 80 }, (_, i) => 130 + ((i * 13) % 44) - 22);\nconst test = Array.from({ length: 80 }, (_, i) => 116 + ((i * 13) % 44) - 22);\n\n<ABStrips data={{ a: control, b: test }} positive=\"down\" title=\"Latency A/B\" />"
        }
      ]
    },
    {
      "name": "ShiftHistogram",
      "slug": "shift-histogram",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/shift-histogram",
      "staticImport": "@microcharts/react/shift-histogram",
      "interactiveImport": "@microcharts/react/shift-histogram/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ before: number[]; after: number[] }",
      "primaryEncoding": "mirrored bin heights around a center + median shift",
      "bestFor": [
        "a \"the fix, proven\" read in a KPI card",
        "before/after distributions in an experiments table",
        "showing a change is real, not just a mean move"
      ],
      "avoidFor": [
        "a single distribution (HistogramStrip)",
        "two labelled arms (ABStrips)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ before: number[]; after: number[] }",
          "required": true,
          "description": "The two samples — raw observations, shared bin edges are derived."
        },
        {
          "name": "bins",
          "type": "number",
          "required": false,
          "description": "Shared bin count (default auto, Sturges capped at 12)."
        },
        {
          "name": "mode",
          "type": "\"mirror\" | \"overlay\"",
          "required": false,
          "description": "Mirror (default) or after-as-outline over before fill."
        },
        {
          "name": "seriesLabels",
          "type": "[string, string]",
          "required": false,
          "description": "Side identities for the summary (default ['before', 'after'])."
        },
        {
          "name": "label",
          "type": "\"shift\" | \"none\"",
          "required": false,
          "description": "Signed median shift in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "The fix",
          "code": "import { ShiftHistogram } from \"@microcharts/react/shift-histogram\";\n\n<ShiftHistogram data={{ before, after }} title=\"The fix\" />"
        }
      ]
    },
    {
      "name": "ParetoStrip",
      "slug": "pareto-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/pareto-strip",
      "staticImport": "@microcharts/react/pareto-strip",
      "interactiveImport": "@microcharts/react/pareto-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label: string; value: number }[]",
      "primaryEncoding": "descending bar magnitude + cumulative-share line on a fixed 0–100% scale",
      "bestFor": [
        "a \"fix these three\" read in a KPI card",
        "incident causes or support tags in a tab header",
        "any long-tail composition where a few dominate"
      ],
      "avoidFor": [
        "a plain ranking (MiniBar)",
        "parts of a single whole (SegmentedBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label; value }[]",
          "required": true,
          "description": "Categories with magnitudes — the component sorts descending."
        },
        {
          "name": "threshold",
          "type": "number | false",
          "required": false,
          "description": "Cumulative reference line % (default 80 — a working reference, not a law)."
        },
        {
          "name": "maxItems",
          "type": "number",
          "required": false,
          "description": "Categories beyond maxItems roll up into Other (default 8, always last)."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Category noun for the summary (default 'causes')."
        },
        {
          "name": "metric",
          "type": "string",
          "required": false,
          "description": "Total-metric noun for the summary (default 'the total')."
        },
        {
          "name": "label",
          "type": "\"count\" | \"none\"",
          "required": false,
          "description": "'K of N → cum%' in a right gutter."
        }
      ],
      "examples": [
        {
          "title": "Incident causes",
          "code": "import { ParetoStrip } from \"@microcharts/react/pareto-strip\";\n\n<ParetoStrip data={causes} unit=\"causes\" metric=\"incidents\" title=\"Incident causes\" />"
        }
      ]
    },
    {
      "name": "DataDiff",
      "slug": "data-diff",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/data-diff",
      "staticImport": "@microcharts/react/data-diff",
      "interactiveImport": "@microcharts/react/data-diff/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ key: string; added: number; removed: number }[]",
      "primaryEncoding": "diverging bar length per key — removed left, added right, one symmetric scale",
      "bestFor": [
        "a table cell per dataset version",
        "a KPI card for a sync or import job",
        "any per-key added/removed audit where churn matters"
      ],
      "avoidFor": [
        "a plain ranking (MiniBar)",
        "parts of a single whole (SegmentedBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ key; added; removed }[]",
          "required": true,
          "description": "Per-key change counts — added and removed are non-negative magnitudes."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "In-chart key tags for standalone use (host tables carry keys by default)."
        },
        {
          "name": "net",
          "type": "boolean",
          "required": false,
          "description": "A tick at added−removed per row — a summary mark, never the two bars."
        },
        {
          "name": "order",
          "type": "\"data\" | \"net\" | \"magnitude\"",
          "required": false,
          "description": "Default 'data' keeps input order (schema order is often meaningful)."
        },
        {
          "name": "label",
          "type": "\"totals\" | \"none\"",
          "required": false,
          "description": "'totals' prints a +added / −removed footer."
        },
        {
          "name": "maxItems",
          "type": "number",
          "required": false,
          "description": "Row cap (default 12); rows beyond it are dropped with a dev warning."
        }
      ],
      "examples": [
        {
          "title": "Schema diff",
          "code": "import { DataDiff } from \"@microcharts/react/data-diff\";\n\n<DataDiff data={diff} title=\"Schema diff\" />"
        }
      ]
    },
    {
      "name": "QuadrantDot",
      "slug": "quadrant-dot",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/quadrant-dot",
      "staticImport": "@microcharts/react/quadrant-dot",
      "interactiveImport": "@microcharts/react/quadrant-dot/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ x: number; y: number } + field?: { x; y }[]",
      "primaryEncoding": "2-D position vs a quadrant split",
      "bestFor": [
        "a table cell per initiative — the classic prioritization 2×2",
        "an effort vs impact read in a KPI card",
        "any 'which quadrant, against the field' decision"
      ],
      "avoidFor": [
        "a full scatter plot (MicroScatter)",
        "a single ranked list (MiniBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ x; y }",
          "required": true,
          "description": "The focal item's 2-D position."
        },
        {
          "name": "field",
          "type": "{ x; y }[]",
          "required": false,
          "description": "The peer set — omit for a lone glyph."
        },
        {
          "name": "xDomain",
          "type": "[number, number]",
          "required": false,
          "description": "The x-axis range (default: derived from the data); domain stays the y-axis."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "The y-axis range (default: derived from the data)."
        },
        {
          "name": "split",
          "type": "[number, number]",
          "required": false,
          "description": "The quadrant boundary (default domain midpoints) — never hidden."
        },
        {
          "name": "quadrants",
          "type": "[TL, TR, BL, BR]",
          "required": false,
          "description": "Names in reading order — summaries only, never rendered."
        },
        {
          "name": "xLabel / yLabel",
          "type": "string",
          "required": false,
          "description": "Axis nouns for the summary — pass them, the axes are unlabeled at glyph size."
        },
        {
          "name": "region",
          "type": "boolean",
          "required": false,
          "description": "Faint tint on the focal's quadrant (default true; false for dense grids)."
        }
      ],
      "examples": [
        {
          "title": "Effort vs impact",
          "code": "import { QuadrantDot } from \"@microcharts/react/quadrant-dot\";\n\n<QuadrantDot data={item} field={backlog} xLabel=\"effort\" yLabel=\"impact\" title=\"Effort vs impact\" />"
        }
      ]
    },
    {
      "name": "CyclePlot",
      "slug": "cycle-plot",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/cycle-plot",
      "staticImport": "@microcharts/react/cycle-plot",
      "interactiveImport": "@microcharts/react/cycle-plot/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[] + period: number",
      "primaryEncoding": "slot-mean spine + within-slot micro-trend",
      "bestFor": [
        "a KPI card — the week (or month) has a shape",
        "weekday traffic, hourly load, monthly sales seasonality",
        "spotting a single slot that is itself drifting"
      ],
      "avoidFor": [
        "a plain time series (Sparkline)",
        "one composition (SegmentedBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "A flat series, reshaped row-major into `period` slots."
        },
        {
          "name": "period",
          "type": "number",
          "required": true,
          "description": "Slots per cycle (4–12) — e.g. 7 for weekdays."
        },
        {
          "name": "slots",
          "type": "string[]",
          "required": false,
          "description": "Slot names for summaries, e.g. weekday labels."
        },
        {
          "name": "center",
          "type": "\"mean\" | \"median\"",
          "required": false,
          "description": "Center statistic — median for skewed slot distributions."
        },
        {
          "name": "trend",
          "type": "boolean",
          "required": false,
          "description": "Within-slot micro-trend line (default true); false = spine + ticks only."
        },
        {
          "name": "spine",
          "type": "boolean",
          "required": false,
          "description": "The slot-center spine (default true); false leaves within-slot drift only."
        },
        {
          "name": "cycleUnit",
          "type": "string",
          "required": false,
          "description": "Cycle noun for the summary, e.g. 'weeks' (default 'cycles')."
        }
      ],
      "examples": [
        {
          "title": "Weekly shape",
          "code": "import { CyclePlot } from \"@microcharts/react/cycle-plot\";\n\n<CyclePlot data={daily} period={7} slots={weekdays} cycleUnit=\"weeks\" title=\"Weekly shape\" />"
        }
      ]
    },
    {
      "name": "ChangePoint",
      "slug": "change-point",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/change-point",
      "staticImport": "@microcharts/react/change-point",
      "interactiveImport": "@microcharts/react/change-point/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[]",
      "primaryEncoding": "break marker position + regime shading",
      "bestFor": [
        "context for an anomaly — a spike means nothing without the regime it broke",
        "error rate / latency / cost that stepped to a new level",
        "annotating a known deploy or incident (pass explicit `breaks`)"
      ],
      "avoidFor": [
        "a gradual trend (Sparkline)",
        "a plain time series with no regime question"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "A single series."
        },
        {
          "name": "breaks",
          "type": "\"auto\" | number[]",
          "required": false,
          "description": "Explicit indices override the heuristic entirely — the production path."
        },
        {
          "name": "maxItems",
          "type": "number",
          "required": false,
          "description": "Max detected breaks (1–3). More regimes stop being glanceable."
        },
        {
          "name": "means",
          "type": "boolean",
          "required": false,
          "description": "Per-regime mean hairlines (default true)."
        },
        {
          "name": "label",
          "type": "\"delta\" | \"none\"",
          "required": false,
          "description": "Signed % across the most recent break, in a gutter."
        }
      ],
      "examples": [
        {
          "title": "Error rate",
          "code": "import { ChangePoint } from \"@microcharts/react/change-point\";\n\n<ChangePoint data={errors} label=\"delta\" title=\"Error rate\" />"
        }
      ]
    },
    {
      "name": "EnsembleGhosts",
      "slug": "ensemble-ghosts",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/ensemble-ghosts",
      "staticImport": "@microcharts/react/ensemble-ghosts",
      "interactiveImport": "@microcharts/react/ensemble-ghosts/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[][] (2–50 members)",
      "primaryEncoding": "path-bundle spread + one emphasized representative",
      "bestFor": [
        "a KPI card — the futures, not the average",
        "Monte-Carlo / simulation output where paths disagree in shape",
        "showing that outcomes fan out, not just their endpoint range"
      ],
      "avoidFor": [
        "interval precision (ForecastCone)",
        "a single path (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[][]",
          "required": true,
          "description": "Ensemble members — 2–50 simulated paths."
        },
        {
          "name": "ghosts",
          "type": "number",
          "required": false,
          "description": "Rendered member count (deterministic endpoint-rank selection). Default 8, cap 12."
        },
        {
          "name": "emphasis",
          "type": "\"nearest-median\" | \"median\" | number",
          "required": false,
          "description": "A real median-like member, the synthetic median, or a pinned member."
        },
        {
          "name": "endpoints",
          "type": "boolean",
          "required": false,
          "description": "Ghost endpoint dots — makes the final-value spread countable."
        },
        {
          "name": "label",
          "type": "\"end\" | \"none\"",
          "required": false,
          "description": "Emphasised path endpoint in a right gutter (default end)."
        }
      ],
      "examples": [
        {
          "title": "Simulated futures",
          "code": "import { EnsembleGhosts } from \"@microcharts/react/ensemble-ghosts\";\n\n<EnsembleGhosts data={futures} title=\"Simulated futures\" />"
        }
      ]
    },
    {
      "name": "TallyMarks",
      "slug": "tally-marks",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/tally-marks",
      "staticImport": "@microcharts/react/tally-marks",
      "interactiveImport": "@microcharts/react/tally-marks/interactive",
      "picker": false,
      "animates": false,
      "sharedInteractive": [
        "live",
        "onSelect"
      ],
      "dataShape": "{ value: number }",
      "primaryEncoding": "mark count in four-and-strike clusters of five",
      "bestFor": [
        "a small running count in a sentence or cell",
        "a live event or score counter",
        "editorial / hand-tallied contexts (the drawn pen)"
      ],
      "avoidFor": [
        "large magnitudes (MiniBar)",
        "trends over time (Sparkline)",
        "proportions (Progress)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The count. Floored; negatives clamp to 0."
        },
        {
          "name": "total",
          "type": "number",
          "required": false,
          "description": "Marks drawn before overflow (default 25)."
        },
        {
          "name": "overflow",
          "type": "\"numeral\" | \"clamp\"",
          "required": false,
          "description": "numeral appends +N; clamp stops drawing. The summary always keeps the true count."
        },
        {
          "name": "pen",
          "type": "\"ruled\" | \"drawn\"",
          "required": false,
          "description": "Hand-drawn jitter for editorial contexts."
        }
      ],
      "examples": [
        {
          "title": "Signatures",
          "code": "import { TallyMarks } from \"@microcharts/react/tally-marks\";\n\n<TallyMarks value={23} title=\"Signatures\" />"
        }
      ]
    },
    {
      "name": "DicePips",
      "slug": "dice-pips",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/dice-pips",
      "staticImport": "@microcharts/react/dice-pips",
      "interactiveImport": "@microcharts/react/dice-pips/interactive",
      "picker": false,
      "animates": false,
      "sharedInteractive": [
        "live",
        "onSelect"
      ],
      "dataShape": "{ value: number }",
      "primaryEncoding": "canonical pip pattern 1–6 (subitized)",
      "bestFor": [
        "severity or rating 0–6 in a cell",
        "an at-a-glance small count in a sentence",
        "an incident-severity badge"
      ],
      "avoidFor": [
        "counts above 6 (TallyMarks)",
        "magnitudes (MiniBar)",
        "proportions (Progress)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "Integer 0–6 (rounded); above 6 shows a numeral."
        },
        {
          "name": "face",
          "type": "boolean",
          "required": false,
          "description": "Draw the die outline (default true)."
        }
      ],
      "examples": [
        {
          "title": "Severity",
          "code": "import { DicePips } from \"@microcharts/react/dice-pips\";\n\n<DicePips value={4} title=\"Severity\" />"
        }
      ]
    },
    {
      "name": "FillWord",
      "slug": "fill-word",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/fill-word",
      "staticImport": "@microcharts/react/fill-word",
      "interactiveImport": "@microcharts/react/fill-word/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onSelect"
      ],
      "dataShape": "{ word: string; value: number }",
      "primaryEncoding": "inked fraction of the word's own glyph extent",
      "bestFor": [
        "a labelled progress read in a sentence or cell",
        "a sync / upload status where the label names the task",
        "a quota or TTL where the word is the metric"
      ],
      "avoidFor": [
        "precise percentages (Progress)",
        "trends (Sparkline)",
        "many parallel bars (MiniBar)"
      ],
      "props": [
        {
          "name": "word",
          "type": "string",
          "required": true,
          "description": "The text that is the chart."
        },
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "Fraction 0–1 (clamped)."
        },
        {
          "name": "mode",
          "type": "\"fill\" | \"drain\"",
          "required": false,
          "description": "fill grows the ink (complete); drain empties it (remaining / TTL)."
        },
        {
          "name": "label",
          "type": "\"none\" | \"value\"",
          "required": false,
          "description": "Append the percent numeral after the word."
        }
      ],
      "examples": [
        {
          "title": "Upload",
          "code": "import { FillWord } from \"@microcharts/react/fill-word\";\n\n<FillWord word=\"uploading\" value={0.62} />"
        }
      ]
    },
    {
      "name": "FatDigits",
      "slug": "fat-digits",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/fat-digits",
      "staticImport": "@microcharts/react/fat-digits",
      "interactiveImport": "@microcharts/react/fat-digits/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onSelect"
      ],
      "dataShape": "{ value: number }",
      "primaryEncoding": "the numeral + redundant font-weight tier",
      "bestFor": [
        "a dense numeric table column you scan for the big ones",
        "a KPI number that should carry its own magnitude",
        "an amount in a sentence"
      ],
      "avoidFor": [
        "trends (Sparkline)",
        "proportions (Progress)",
        "comparisons (MiniBar)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The number (always the exact value)."
        },
        {
          "name": "domain",
          "type": "readonly [number, number]",
          "required": false,
          "description": "Maps value to a weight tier — always pass one."
        },
        {
          "name": "encode",
          "type": "\"value\" | \"digit\"",
          "required": false,
          "description": "value weights the whole numeral; digit weights each digit by its own magnitude."
        },
        {
          "name": "tiers",
          "type": "3 | 5",
          "required": false,
          "description": "Weight steps (default 5)."
        }
      ],
      "examples": [
        {
          "title": "Revenue",
          "code": "import { FatDigits } from \"@microcharts/react/fat-digits\";\n\n<FatDigits value={1204} domain={[0, 2100]} title=\"Revenue\" />"
        }
      ]
    },
    {
      "name": "Thermometer",
      "slug": "thermometer",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/thermometer",
      "staticImport": "@microcharts/react/thermometer",
      "interactiveImport": "@microcharts/react/thermometer/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onSelect",
        "readout"
      ],
      "dataShape": "{ value: number; target?: number }",
      "primaryEncoding": "column extent on a ticked calibrated scale",
      "bestFor": [
        "a fundraising or goal progress read",
        "a capacity or utilization gauge in a cell",
        "any value against a stated range"
      ],
      "avoidFor": [
        "trends (Sparkline)",
        "proportions of a whole (SegmentedBar)",
        "many series"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The reading."
        },
        {
          "name": "target",
          "type": "number",
          "required": false,
          "description": "A goal tick across the tube."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "The calibrated range (default [0, 100])."
        },
        {
          "name": "ticks",
          "type": "number | number[]",
          "required": false,
          "description": "Tick count or explicit values."
        },
        {
          "name": "orientation",
          "type": "\"vertical\" | \"horizontal\"",
          "required": false,
          "description": "Horizontal fits table cells."
        },
        {
          "name": "bulb",
          "type": "boolean",
          "required": false,
          "description": "Draw the reservoir bulb (default true)."
        }
      ],
      "examples": [
        {
          "title": "Fundraiser",
          "code": "import { Thermometer } from \"@microcharts/react/thermometer\";\n\n<Thermometer value={72} target={80} title=\"Fundraiser\" />"
        }
      ]
    },
    {
      "name": "MoonPhase",
      "slug": "moon-phase",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/moon-phase",
      "staticImport": "@microcharts/react/moon-phase",
      "interactiveImport": "@microcharts/react/moon-phase/interactive",
      "picker": false,
      "animates": false,
      "sharedInteractive": [
        "live",
        "onSelect",
        "readout"
      ],
      "dataShape": "{ value: number }",
      "primaryEncoding": "illuminated area fraction of the disc",
      "bestFor": [
        "sprint or quota progress in a sentence",
        "a billing-period or release-cycle marker",
        "any 0–1 completion that reads at a glance"
      ],
      "avoidFor": [
        "exact percentages (Progress)",
        "trends (Sparkline)",
        "comparisons (MiniBar)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "Fraction 0–1 (clamped)."
        },
        {
          "name": "mode",
          "type": "\"progress\" | \"cycle\"",
          "required": false,
          "description": "progress = monotonic fill; cycle = true lunar mapping (0 new → 0.5 full → 1 new)."
        }
      ],
      "examples": [
        {
          "title": "Sprint",
          "code": "import { MoonPhase } from \"@microcharts/react/moon-phase\";\n\n<MoonPhase value={0.68} title=\"Sprint\" />"
        }
      ]
    },
    {
      "name": "Hourglass",
      "slug": "hourglass",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/hourglass",
      "staticImport": "@microcharts/react/hourglass",
      "interactiveImport": "@microcharts/react/hourglass/interactive",
      "picker": false,
      "animates": false,
      "sharedInteractive": [
        "live",
        "onSelect"
      ],
      "dataShape": "{ value: number }",
      "primaryEncoding": "sand area split top (remaining) / bottom (elapsed)",
      "bestFor": [
        "a deadline or session-expiry read in a sentence",
        "a TTL cell where remaining is the story",
        "a time-boxed tab or countdown"
      ],
      "avoidFor": [
        "exact percentages (Progress)",
        "trends (Sparkline)",
        "non-time fractions"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "Elapsed fraction 0–1 (like Progress)."
        },
        {
          "name": "stream",
          "type": "boolean",
          "required": false,
          "description": "The running-sand cue (default true)."
        },
        {
          "name": "label",
          "type": "\"none\" | \"remaining\" | \"elapsed\"",
          "required": false,
          "description": "Print the percent that matters to the context."
        }
      ],
      "examples": [
        {
          "title": "Session",
          "code": "import { Hourglass } from \"@microcharts/react/hourglass\";\n\n<Hourglass value={0.75} title=\"Session\" />"
        }
      ]
    },
    {
      "name": "BalanceBeam",
      "slug": "balance-beam",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/balance-beam",
      "staticImport": "@microcharts/react/balance-beam",
      "interactiveImport": "@microcharts/react/balance-beam/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "[{ label, value }, { label, value }]",
      "primaryEncoding": "beam tilt direction + saturating angle",
      "bestFor": [
        "a buy vs sell or in vs out read in a sentence",
        "a pro vs con weight in a KPI card",
        "an A-vs-B pair where direction is the story"
      ],
      "avoidFor": [
        "exact ratios (PairedBars / Delta)",
        "more than two items (MiniBar)",
        "trends"
      ],
      "props": [
        {
          "name": "data",
          "type": "[{label,value},{label,value}]",
          "required": true,
          "description": "Exactly two items."
        },
        {
          "name": "maxTilt",
          "type": "number",
          "required": false,
          "description": "Degrees at full saturation (default 12)."
        },
        {
          "name": "shape",
          "type": "\"square\" | \"round\"",
          "required": false,
          "description": "Weight shape (default square)."
        },
        {
          "name": "mode",
          "type": "\"ratio\" | \"difference\"",
          "required": false,
          "description": "ratio = share-of-whole; difference = absolute, scaled by domain."
        }
      ],
      "examples": [
        {
          "title": "Cash flow",
          "code": "import { BalanceBeam } from \"@microcharts/react/balance-beam\";\n\n<BalanceBeam data={[{ label: \"Inflow\", value: 620 }, { label: \"Outflow\", value: 480 }]} />"
        }
      ]
    },
    {
      "name": "SproutRow",
      "slug": "sprout-row",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/sprout-row",
      "staticImport": "@microcharts/react/sprout-row",
      "interactiveImport": "@microcharts/react/sprout-row/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label: string; value: 0 | 1 | 2 | 3 }[]",
      "primaryEncoding": "ordinal growth-stage glyph (height monotonic)",
      "bestFor": [
        "account or project maturity across a small set",
        "a health column in a portfolio table",
        "per-item lifecycle in a KPI card"
      ],
      "avoidFor": [
        "continuous values (MiniBar)",
        "trends (Sparkline)",
        "more than ~12 items"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label, value }[]",
          "required": true,
          "description": "value = stage 0–3."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Category labels under the slots."
        },
        {
          "name": "label",
          "type": "\"none\" | \"value\"",
          "required": false,
          "description": "Print the stage number above each glyph."
        },
        {
          "name": "step",
          "type": "number",
          "required": false,
          "description": "Horizontal spacing between glyph slots (default 16; widens for labels)."
        }
      ],
      "examples": [
        {
          "title": "Account health",
          "code": "import { SproutRow } from \"@microcharts/react/sprout-row\";\n\n<SproutRow data={accounts} title=\"Account health\" />"
        }
      ]
    },
    {
      "name": "GardenGrid",
      "slug": "garden-grid",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/garden-grid",
      "staticImport": "@microcharts/react/garden-grid",
      "interactiveImport": "@microcharts/react/garden-grid/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(number | null)[]",
      "primaryEncoding": "dot area, quantized to 5 ordinal steps",
      "bestFor": [
        "a contribution or activity rhythm you print or read in grayscale",
        "a per-repo or per-team activity strip",
        "any calendar-shaped intensity where color isn't available"
      ],
      "avoidFor": [
        "exact per-cell values (ActivityGrid + hover / HeatStrip)",
        "trends (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "Binned values; null = missing."
        },
        {
          "name": "rows",
          "type": "number",
          "required": false,
          "description": "Grid rows (default 7); 1 = strip."
        },
        {
          "name": "steps",
          "type": "3 | 5",
          "required": false,
          "description": "Radius quantization steps (default 5)."
        },
        {
          "name": "empty",
          "type": "\"outline\" | \"blank\"",
          "required": false,
          "description": "How zero cells render (default outline)."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Noun for the summary count (default \"periods\")."
        }
      ],
      "examples": [
        {
          "title": "Activity",
          "code": "import { GardenGrid } from \"@microcharts/react/garden-grid\";\n\n<GardenGrid data={weeks} title=\"Activity\" unit=\"weeks\" />"
        }
      ]
    },
    {
      "name": "BubbleRow",
      "slug": "bubble-row",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/bubble-row",
      "staticImport": "@microcharts/react/bubble-row",
      "interactiveImport": "@microcharts/react/bubble-row/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label: string; value: number }[]",
      "primaryEncoding": "circle area (r ∝ √value)",
      "bestFor": [
        "a few magnitudes with physical presence in a sentence",
        "a market-size or segment impression in a KPI card",
        "an editorial callout where the number is printed too"
      ],
      "avoidFor": [
        "precise comparison (MiniBar)",
        "trends (Sparkline)",
        "more than ~8 items"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label, value }[]",
          "required": true,
          "description": "A few non-negative magnitudes."
        },
        {
          "name": "align",
          "type": "\"center\" | \"baseline\"",
          "required": false,
          "description": "center (specimen) or baseline (weights on a shelf)."
        },
        {
          "name": "label",
          "type": "\"value\" | \"both\" | \"none\"",
          "required": false,
          "description": "value (default), both, or none."
        }
      ],
      "examples": [
        {
          "title": "Market size",
          "code": "import { BubbleRow } from \"@microcharts/react/bubble-row\";\n\n<BubbleRow data={regions} title=\"Market size\" />"
        }
      ]
    },
    {
      "name": "MusicStaff",
      "slug": "music-staff",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/music-staff",
      "staticImport": "@microcharts/react/music-staff",
      "interactiveImport": "@microcharts/react/music-staff/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(number | null)[]",
      "primaryEncoding": "pitch (vertical position on a 5-line staff)",
      "bestFor": [
        "a weekly-rhythm read in a sentence",
        "the shape of a sprint or short series in a cell",
        "a per-channel melody in a tab"
      ],
      "avoidFor": [
        "exact values (Sparkline + label)",
        "long series (> 16 points)",
        "trends where slope matters"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "The series; null = a rest."
        },
        {
          "name": "mode",
          "type": "\"staff\" | \"ledger\"",
          "required": false,
          "description": "ledger (±2, default) or staff (clamp on-staff)."
        },
        {
          "name": "label",
          "type": "\"none\" | \"last\"",
          "required": false,
          "description": "Print the final value after the last note."
        }
      ],
      "examples": [
        {
          "title": "Sprint melody",
          "code": "import { MusicStaff } from \"@microcharts/react/music-staff\";\n\n<MusicStaff data={weeks} title=\"Sprint melody\" />"
        }
      ]
    },
    {
      "name": "TreeRings",
      "slug": "tree-rings",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/tree-rings",
      "staticImport": "@microcharts/react/tree-rings",
      "interactiveImport": "@microcharts/react/tree-rings/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[] (oldest first)",
      "primaryEncoding": "radial ring thickness ∝ per-period value",
      "bestFor": [
        "account or company age at a glance",
        "a cohort-age marker in a table cell",
        "a per-period growth story in a KPI card"
      ],
      "avoidFor": [
        "exact per-period reads (SparkBar)",
        "many periods (> 24)",
        "non-cumulative series"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Per-period growth, oldest first."
        },
        {
          "name": "highlight",
          "type": "\"last\" | \"none\" | number",
          "required": false,
          "description": "Which period's ring to pick out."
        },
        {
          "name": "total",
          "type": "number",
          "required": false,
          "description": "Expected lifetime Σ — the disc fills only Σdata/total."
        },
        {
          "name": "rings",
          "type": "\"stroke\" | \"fill\"",
          "required": false,
          "description": "Boundary rings (default) or filled annuli."
        },
        {
          "name": "periodWord",
          "type": "string",
          "required": false,
          "description": "Singular period noun for the summary (default \"period\")."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Plural period noun for the summary (default \"periods\")."
        }
      ],
      "examples": [
        {
          "title": "Account age",
          "code": "import { TreeRings } from \"@microcharts/react/tree-rings\";\n\n<TreeRings data={years} unit=\"years\" periodWord=\"year\" title=\"Account age\" />"
        }
      ]
    },
    {
      "name": "CitySkyline",
      "slug": "city-skyline",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/city-skyline",
      "staticImport": "@microcharts/react/city-skyline",
      "interactiveImport": "@microcharts/react/city-skyline/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label: string; value: number; lit?: number }[]",
      "primaryEncoding": "building height (primary) + lit-window fraction (secondary)",
      "bestFor": [
        "team or region size plus an activation read",
        "an org KPI where two variables are the story",
        "a per-BU comparison with utilization"
      ],
      "avoidFor": [
        "a single variable (MiniBar)",
        "precise activation reads",
        "more than ~8 groups"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label, value, lit? }[]",
          "required": true,
          "description": "value = height; lit = 0–1 window fraction."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Category labels under the buildings."
        },
        {
          "name": "ground",
          "type": "boolean",
          "required": false,
          "description": "The baseline hairline (default true)."
        },
        {
          "name": "label",
          "type": "\"none\" | \"value\"",
          "required": false,
          "description": "Numeral above each building."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Category noun for the summary (default 'groups')."
        },
        {
          "name": "bw",
          "type": "number",
          "required": false,
          "description": "Building width in viewBox units (default 9)."
        }
      ],
      "examples": [
        {
          "title": "Team sizes",
          "code": "import { CitySkyline } from \"@microcharts/react/city-skyline\";\n\n<CitySkyline data={teams} unit=\"teams\" title=\"Team sizes\" />"
        }
      ]
    },
    {
      "name": "Honeycomb",
      "slug": "honeycomb",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/honeycomb",
      "staticImport": "@microcharts/react/honeycomb",
      "interactiveImport": "@microcharts/react/honeycomb/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "live",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ value: number; total: number }",
      "primaryEncoding": "filled-cell count in a hex grid (unit counting)",
      "bestFor": [
        "seats or licenses taken of a capacity",
        "an occupancy read in a KPI card",
        "a countable of-total in a cell (strip mode)"
      ],
      "avoidFor": [
        "a capacity over ~60 (Progress)",
        "a magnitude with no total (MiniBar)",
        "trends"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "Filled count (fractional rounds)."
        },
        {
          "name": "total",
          "type": "number",
          "required": false,
          "description": "Capacity = cell count (default 10)."
        },
        {
          "name": "rows",
          "type": "number | \"auto\"",
          "required": false,
          "description": "auto (near-square) or a number; 1 = strip."
        },
        {
          "name": "empty",
          "type": "\"outline\" | \"blank\"",
          "required": false,
          "description": "How empty cells render (default outline)."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Noun for the summary (e.g. \"seats\")."
        },
        {
          "name": "label",
          "type": "\"none\" | \"count\" | \"percent\"",
          "required": false,
          "description": "Centered readout when the comb has room (default \"none\")."
        }
      ],
      "examples": [
        {
          "title": "Occupancy",
          "code": "import { Honeycomb } from \"@microcharts/react/honeycomb\";\n\n<Honeycomb value={34} total={40} unit=\"seats\" title=\"Occupancy\" />"
        }
      ]
    },
    {
      "name": "Constellation",
      "slug": "constellation",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/constellation",
      "staticImport": "@microcharts/react/constellation",
      "interactiveImport": "@microcharts/react/constellation/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ x: number; y?: number; m?: number }[]",
      "primaryEncoding": "position (x = time, y = value) + area-true dot size",
      "bestFor": [
        "sparse incidents or outages on a timeline",
        "milestones with a magnitude (severity, size)",
        "rare events where sequence is the story"
      ],
      "avoidFor": [
        "dense event streams (Seismogram / EventTimeline)",
        "a continuous trend (Sparkline)",
        "precise value comparison (dot area is low precision)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ x: number; y?: number; m?: number }[]",
          "required": true,
          "description": "Events: x = time, y = value, m = magnitude (area-true size)."
        },
        {
          "name": "connect",
          "type": "boolean",
          "required": false,
          "description": "The faint chronology line (default true)."
        },
        {
          "name": "label",
          "type": "\"max\" | \"none\"",
          "required": false,
          "description": "Numeral at the largest event."
        },
        {
          "name": "xFormat",
          "type": "(x: number) => string",
          "required": false,
          "description": "Formats time for the summary (e.g. a month name)."
        },
        {
          "name": "xDomain",
          "type": "[number, number]",
          "required": false,
          "description": "Time (x) extent (default: data extent)."
        },
        {
          "name": "rBase",
          "type": "number",
          "required": false,
          "description": "Base dot radius in viewBox units (default 1.6)."
        }
      ],
      "examples": [
        {
          "title": "Incidents",
          "code": "import { Constellation } from \"@microcharts/react/constellation\";\n\n<Constellation\n  data={[\n    { x: 0, y: 40, m: 2 },\n    { x: 2, y: 90, m: 7 },\n    { x: 5, y: 30, m: 3 },\n    { x: 8, y: 65, m: 5 },\n  ]}\n  title=\"Incidents\"\n/>"
        }
      ]
    },
    {
      "name": "PolarClock",
      "slug": "polar-clock",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/polar-clock",
      "staticImport": "@microcharts/react/polar-clock",
      "interactiveImport": "@microcharts/react/polar-clock/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(number | null)[]",
      "primaryEncoding": "radial bar length at a fixed cycle angle",
      "bestFor": [
        "the shape of a 24-hour or 7-day cycle",
        "when a metric is busy across the cycle",
        "a compact seasonal read in a KPI card"
      ],
      "avoidFor": [
        "exact value comparison (SparkBar over the unrolled cycle)",
        "a non-cyclic trend (Sparkline)",
        "more than a few dozen segments"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "One value per cycle division (24 hourly, 7 daily, any n)."
        },
        {
          "name": "now",
          "type": "number",
          "required": false,
          "description": "Index of the current segment to accent."
        },
        {
          "name": "inner",
          "type": "number",
          "required": false,
          "description": "Inner radius fraction r0 — the zero baseline bars grow from (default 0.35)."
        },
        {
          "name": "mode",
          "type": "\"length\" | \"opacity\"",
          "required": false,
          "description": "Radial bars (default) or fixed-length 5-step fill."
        },
        {
          "name": "origin",
          "type": "number",
          "required": false,
          "description": "Index rendered at 12 o'clock (week-start / midnight)."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Hairline cardinal ticks at 0/¼/½/¾ — the at-rest orientation cue. Default true."
        },
        {
          "name": "segmentFormat",
          "type": "(index, n) => string",
          "required": false,
          "description": "Segment index → label (default: HH:00 for n=24, weekday for n=7, else index)."
        }
      ],
      "examples": [
        {
          "title": "Traffic by hour",
          "code": "import { PolarClock } from \"@microcharts/react/polar-clock\";\n\n<PolarClock data={byHour} now={14} title=\"Traffic by hour\" />"
        }
      ]
    },
    {
      "name": "SpiralYear",
      "slug": "spiral-year",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/spiral-year",
      "staticImport": "@microcharts/react/spiral-year",
      "interactiveImport": "@microcharts/react/spiral-year/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(number | null)[]",
      "primaryEncoding": "5-step opacity of marks along a calendar spiral",
      "bestFor": [
        "the seasonal shape of a year at a glance",
        "spotting a busy season or a quiet stretch",
        "a compact 'the year in one square'"
      ],
      "avoidFor": [
        "reading an exact day's value (ActivityGrid / HeatStrip)",
        "a non-cyclic trend (Sparkline)",
        "more than about three years"
      ],
      "props": [
        {
          "name": "data",
          "type": "(number | null)[]",
          "required": true,
          "description": "One value per day or week (cadence inferred from length)."
        },
        {
          "name": "cadence",
          "type": "\"day\" | \"week\"",
          "required": false,
          "description": "Data cadence; inferred from length (≈52 → week, else day) when omitted."
        },
        {
          "name": "startDate",
          "type": "string",
          "required": false,
          "description": "ISO date anchoring index 0 to a calendar angle."
        },
        {
          "name": "steps",
          "type": "3 | 5",
          "required": false,
          "description": "Opacity quantization (default 5)."
        },
        {
          "name": "monthTicks",
          "type": "boolean",
          "required": false,
          "description": "Faint radial month ticks (default true)."
        },
        {
          "name": "mark",
          "type": "\"dot\" | \"arc\"",
          "required": false,
          "description": "Dots (default) or short arc segments."
        }
      ],
      "examples": [
        {
          "title": "Seasonality",
          "code": "import { SpiralYear } from \"@microcharts/react/spiral-year\";\n\n<SpiralYear data={byWeek} title=\"Seasonality\" />"
        }
      ]
    },
    {
      "name": "BreathingDot",
      "slug": "breathing-dot",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/breathing-dot",
      "staticImport": "@microcharts/react/breathing-dot",
      "interactiveImport": "@microcharts/react/breathing-dot/interactive",
      "picker": false,
      "animates": false,
      "sharedInteractive": [
        "onSelect"
      ],
      "dataShape": "{ value: number }",
      "primaryEncoding": "pulse rate + amplitude (static: ring offset) by level",
      "bestFor": [
        "an ambient 'how strained is it right now' read",
        "a live status dot in a header or KPI card",
        "per-node load in a dense table"
      ],
      "avoidFor": [
        "an exact load figure (Progress / Sparkline)",
        "discrete events (HeartbeatBlip)",
        "a trend over time (Sparkline)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "Level 0–1 (clamped). null / NaN → unknown."
        },
        {
          "name": "thresholds",
          "type": "[number, number]",
          "required": false,
          "description": "calm / elevated / strained edges (default [0.5, 0.8])."
        },
        {
          "name": "label",
          "type": "\"value\" | \"none\"",
          "required": false,
          "description": "Percent numeral beside the dot."
        }
      ],
      "examples": [
        {
          "title": "Load",
          "code": "import { BreathingDot } from \"@microcharts/react/breathing-dot\";\n\n<BreathingDot value={0.42} title=\"Load\" />"
        }
      ]
    },
    {
      "name": "HeartbeatBlip",
      "slug": "heartbeat-blip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/heartbeat-blip",
      "staticImport": "@microcharts/react/heartbeat-blip",
      "interactiveImport": "@microcharts/react/heartbeat-blip/interactive",
      "picker": false,
      "animates": false,
      "sharedInteractive": [
        "onSelect"
      ],
      "dataShape": "number[]",
      "primaryEncoding": "a spike per event across the recent window",
      "bestFor": [
        "at-a-glance liveness of a service or stream",
        "request or event rate in a header",
        "per-service liveness in a status table"
      ],
      "avoidFor": [
        "exact event counts (Seismogram / EventTimeline)",
        "a continuous level (BreathingDot)",
        "long-term trends (Sparkline)"
      ],
      "props": [
        {
          "name": "events",
          "type": "number[]",
          "required": true,
          "description": "Event timestamps (ms)."
        },
        {
          "name": "window",
          "type": "number",
          "required": false,
          "description": "The visible recent window in ms (default 60000)."
        },
        {
          "name": "now",
          "type": "number",
          "required": false,
          "description": "Explicit clock — defaults to the latest event (SSR-safe)."
        },
        {
          "name": "label",
          "type": "\"count\" | \"none\"",
          "required": false,
          "description": "Event-count numeral at the right."
        }
      ],
      "examples": [
        {
          "title": "Liveness",
          "code": "import { HeartbeatBlip } from \"@microcharts/react/heartbeat-blip\";\n\n// pass 'now' from your data layer — never Date.now() in a server render\n<HeartbeatBlip events={eventTimestamps} now={serverNow} title=\"Requests\" />"
        }
      ]
    },
    {
      "name": "CometTrail",
      "slug": "comet-trail",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/comet-trail",
      "staticImport": "@microcharts/react/comet-trail",
      "interactiveImport": "@microcharts/react/comet-trail/interactive",
      "picker": true,
      "animates": false,
      "sharedInteractive": [
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex"
      ],
      "dataShape": "number[]",
      "primaryEncoding": "head position (now) + opacity-fading positional trail",
      "bestFor": [
        "a live price or metric with a little recency context",
        "a realtime KPI that should show momentum",
        "per-stream 'where is it now' in a table"
      ],
      "avoidFor": [
        "the full history (Sparkline)",
        "an exact multi-point comparison (Sparkline / DotPlot)",
        "discrete events (HeartbeatBlip)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "The rolling window, oldest → newest (last = now)."
        },
        {
          "name": "trail",
          "type": "number",
          "required": false,
          "description": "Points kept visible (default 12, cap 20)."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Numeral after the head (default last)."
        }
      ],
      "examples": [
        {
          "title": "Now",
          "code": "import { CometTrail } from \"@microcharts/react/comet-trail\";\n\n<CometTrail data={rollingWindow} title=\"Latency\" />"
        }
      ]
    },
    {
      "name": "OrbitStatus",
      "slug": "orbit-status",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/orbit-status",
      "staticImport": "@microcharts/react/orbit-status",
      "interactiveImport": "@microcharts/react/orbit-status/interactive",
      "picker": false,
      "animates": false,
      "sharedInteractive": [
        "onSelect",
        "readout"
      ],
      "dataShape": "{ latency: number; rate: number }",
      "primaryEncoding": "orbit radius = latency, dash density / speed = rate",
      "bestFor": [
        "a live dependency health dot in a service table",
        "latency + rate together in one small mark",
        "an infra status glance"
      ],
      "avoidFor": [
        "exact latency (Sparkline)",
        "exact rate (Delta / MiniBar)",
        "a trend over time (Sparkline)"
      ],
      "props": [
        {
          "name": "latency",
          "type": "number",
          "required": true,
          "description": "Orbit radius (weak — pass a domain)."
        },
        {
          "name": "rate",
          "type": "number",
          "required": true,
          "description": "Dash density / satellite speed."
        },
        {
          "name": "latencyDomain",
          "type": "[number, number]",
          "required": false,
          "description": "Latency extent (insist on it — a lone radius is meaningless)."
        },
        {
          "name": "rateDomain",
          "type": "[number, number]",
          "required": false,
          "description": "Rate extent (default [0, 2·rate])."
        },
        {
          "name": "threshold",
          "type": "number",
          "required": false,
          "description": "Latency threshold: at/above it the satellite doubles + the summary flags it."
        }
      ],
      "examples": [
        {
          "title": "Payments API",
          "code": "import { OrbitStatus } from \"@microcharts/react/orbit-status\";\n\n<OrbitStatus\n  latency={240}\n  rate={12}\n  latencyDomain={[0, 500]}\n  rateDomain={[0, 20]}\n  title=\"Payments API\"\n/>"
        }
      ]
    },
    {
      "name": "TimeInRange",
      "slug": "time-in-range",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/time-in-range",
      "staticImport": "@microcharts/react/time-in-range",
      "interactiveImport": "@microcharts/react/time-in-range/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ severeBelow?, below, in, above, severeAbove? } (counts or fractions)",
      "primaryEncoding": "stacked share length in fixed semantic order",
      "bestFor": [
        "SLO / uptime corridors",
        "glucose-style time-in-range KPI"
      ],
      "avoidFor": [
        "ranking parts (SegmentedBar)",
        "a single ratio (Progress)"
      ],
      "props": [
        {
          "name": "data",
          "type": "TimeInRangeDatum",
          "required": true,
          "description": "Counts or fractions; normalized to 1."
        },
        {
          "name": "orientation",
          "type": "\"horizontal\" | \"vertical\"",
          "required": false,
          "description": "Vertical suits clinical columns and KPI cards."
        },
        {
          "name": "label",
          "type": "\"in\" | \"all\" | \"none\"",
          "required": false,
          "description": "The in-range headline, a full audit, or clean."
        }
      ],
      "examples": [
        {
          "title": "Glucose time-in-range",
          "code": "import { TimeInRange } from \"@microcharts/react/time-in-range\";\n\n<TimeInRange data={{ below: 9, in: 72, above: 19 }} title=\"Time in range\" />"
        }
      ]
    },
    {
      "name": "Hypnogram",
      "slug": "hypnogram",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/hypnogram",
      "staticImport": "@microcharts/react/hypnogram",
      "interactiveImport": "@microcharts/react/hypnogram/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ t, state }[] (state holds until the next entry)",
      "primaryEncoding": "row position (y = state, x = time), no interpolation",
      "bestFor": [
        "sleep stages",
        "deploy / machine / incident state over time"
      ],
      "avoidFor": [
        "continuous signals (Sparkline)",
        "a single current state (StatusDot)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ t, state }[]",
          "required": true,
          "description": "State holds from t to the next entry."
        },
        {
          "name": "states",
          "type": "string[]",
          "required": false,
          "description": "Row order top→bottom; ordinal semantics live here."
        },
        {
          "name": "emphasis",
          "type": "string",
          "required": false,
          "description": "Accents one state — the decision read."
        },
        {
          "name": "mode",
          "type": "\"steps\" | \"lanes\"",
          "required": false,
          "description": "Lanes for nominal states with no rank."
        },
        {
          "name": "connectors",
          "type": "boolean",
          "required": false,
          "description": "Vertical transition strokes (default true); off for ultra-dense strips."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Left-gutter state names (default: on when width ≥ 96)."
        },
        {
          "name": "colors",
          "type": "string[]",
          "required": false,
          "description": "Per-state lane colours (lanes mode), cycled; overrides --mc-cat-N."
        }
      ],
      "examples": [
        {
          "title": "Sleep stages",
          "code": "import { Hypnogram } from \"@microcharts/react/hypnogram\";\n\n<Hypnogram data={sleep} states={[\"Awake\",\"REM\",\"Light\",\"Deep\"]} title=\"Sleep stages\" />"
        }
      ]
    },
    {
      "name": "EtaBar",
      "slug": "eta-bar",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/eta-bar",
      "staticImport": "@microcharts/react/eta-bar",
      "interactiveImport": "@microcharts/react/eta-bar/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onSelect",
        "readout"
      ],
      "dataShape": "{ progress, elapsed, rate? }",
      "primaryEncoding": "time axis — elapsed vs predicted-remaining",
      "bestFor": [
        "download / export progress",
        "job-queue ETA"
      ],
      "avoidFor": [
        "fraction-only progress (Progress)",
        "unbounded counters (Delta)"
      ],
      "props": [
        {
          "name": "progress",
          "type": "number",
          "required": true,
          "description": "Completed fraction 0–1."
        },
        {
          "name": "elapsed",
          "type": "number",
          "required": true,
          "description": "Time spent, any unit."
        },
        {
          "name": "rate",
          "type": "number",
          "required": false,
          "description": "Progress per time unit — pass a recent-window rate."
        },
        {
          "name": "label",
          "type": "\"eta\" | \"percent\" | \"none\"",
          "required": false,
          "description": "The remaining-time read is the product."
        },
        {
          "name": "etaFormat",
          "type": "(t: number) => string",
          "required": false,
          "description": "Unit-bearing ETA label (\"2 min\") — the caller owns units."
        },
        {
          "name": "announceEvery",
          "type": "number",
          "required": false,
          "description": "Minimum ms between live-region announcements as the ETA streams (default 10000).",
          "interactive": true
        }
      ],
      "examples": [
        {
          "title": "Export progress",
          "code": "import { EtaBar } from \"@microcharts/react/eta-bar\";\n\n<EtaBar progress={0.64} elapsed={3.6} rate={0.18} etaFormat={(t) => `${Math.round(t)} min`} title=\"Export\" />"
        }
      ]
    },
    {
      "name": "Waveform",
      "slug": "waveform",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/waveform",
      "staticImport": "@microcharts/react/waveform",
      "interactiveImport": "@microcharts/react/waveform/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[] (amplitude samples, may be long)",
      "primaryEncoding": "mirrored bar height = per-bucket max amplitude",
      "bestFor": [
        "voice-memo / audio scrubbers",
        "high-frequency log volume"
      ],
      "avoidFor": [
        "exact values (Sparkline)",
        "categorical state (Hypnogram)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Amplitude samples; negatives allowed."
        },
        {
          "name": "progress",
          "type": "number",
          "required": false,
          "description": "0–1 played fraction; left buckets tint accent."
        },
        {
          "name": "mode",
          "type": "\"bars\" | \"envelope\"",
          "required": false,
          "description": "Envelope draws the min/max area."
        },
        {
          "name": "mirror",
          "type": "boolean",
          "required": false,
          "description": "Mirror around center; false for magnitude-only."
        }
      ],
      "examples": [
        {
          "title": "Voice memo",
          "code": "import { Waveform } from \"@microcharts/react/waveform\";\n\n<Waveform data={samples} title=\"Voice memo\" />"
        }
      ]
    },
    {
      "name": "EventRaster",
      "slug": "event-raster",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/event-raster",
      "staticImport": "@microcharts/react/event-raster",
      "interactiveImport": "@microcharts/react/event-raster/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, events: number[] }[] (one lane per source)",
      "primaryEncoding": "position (x = time, y = lane)",
      "bestFor": [
        "service events across sources",
        "agent steps / cron / sensor triggers"
      ],
      "avoidFor": [
        "a single lane (RugStrip)",
        "continuous rates (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label, events }[]",
          "required": true,
          "description": "One lane per source."
        },
        {
          "name": "emphasis",
          "type": "string",
          "required": false,
          "description": "Accents one lane — the sync read."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Left-gutter lane names (on ≤ 8 lanes)."
        },
        {
          "name": "overflow",
          "type": "\"bin\" | \"clip\"",
          "required": false,
          "description": "Aliasing lanes bin to counts (disclosed)."
        }
      ],
      "examples": [
        {
          "title": "Service events",
          "code": "import { EventRaster } from \"@microcharts/react/event-raster\";\n\n<EventRaster data={services} title=\"Service events\" />"
        }
      ]
    },
    {
      "name": "RubricStrip",
      "slug": "rubric-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/rubric-strip",
      "staticImport": "@microcharts/react/rubric-strip",
      "interactiveImport": "@microcharts/react/rubric-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, score, weight? }[]",
      "primaryEncoding": "bar length = score, bar thickness = weight",
      "bestFor": [
        "model / code-review scorecards",
        "weighted vendor comparison"
      ],
      "avoidFor": [
        "one criterion (Bullet)",
        "parts of a whole (SegmentedBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label, score, weight? }[]",
          "required": true,
          "description": "Criteria; weights default equal."
        },
        {
          "name": "target",
          "type": "number",
          "required": false,
          "description": "Pass target — one tick across all rows."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Criterion names in the left gutter."
        }
      ],
      "examples": [
        {
          "title": "Model eval",
          "code": "import { RubricStrip } from \"@microcharts/react/rubric-strip\";\n\n<RubricStrip\n  data={[\n    { label: \"Correctness\", score: 0.92, weight: 3 },\n    { label: \"Coverage\", score: 0.78, weight: 2 },\n    { label: \"Clarity\", score: 0.65, weight: 1 },\n    { label: \"Style\", score: 0.41, weight: 1 },\n  ]}\n  title=\"Model eval\"\n/>"
        }
      ]
    },
    {
      "name": "TokenConfidence",
      "slug": "token-confidence",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/token-confidence",
      "staticImport": "@microcharts/react/token-confidence",
      "interactiveImport": "@microcharts/react/token-confidence/interactive",
      "picker": false,
      "animates": false,
      "sharedInteractive": [],
      "dataShape": "{ token, confidence }[] (confidence 0–1)",
      "primaryEncoding": "typographic underline tier (color + thickness + style)",
      "bestFor": [
        "LLM answers in chat / transcripts",
        "flagging text to review"
      ],
      "avoidFor": [
        "numeric confidence auditing (CalibrationStrip)",
        "a single score (Delta)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ token, confidence }[]",
          "required": true,
          "description": "Tokens + confidences."
        },
        {
          "name": "tiers",
          "type": "readonly [number, number]",
          "required": false,
          "description": "lo/hi thresholds — the only tuning."
        },
        {
          "name": "show",
          "type": "\"flagged\" | \"all\"",
          "required": false,
          "description": "All also hairlines confident tokens."
        },
        {
          "name": "legend",
          "type": "boolean",
          "required": false,
          "description": "Appends the 1-line inline key."
        }
      ],
      "examples": [
        {
          "title": "Model answer",
          "code": "import { TokenConfidence } from \"@microcharts/react/token-confidence\";\n\n<TokenConfidence data={tokens} title=\"Model answer\" />"
        }
      ]
    },
    {
      "name": "WindBarb",
      "slug": "wind-barb",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/wind-barb",
      "staticImport": "@microcharts/react/wind-barb",
      "dataShape": "{ direction, magnitude }",
      "primaryEncoding": "shaft angle + quantized barb count",
      "bestFor": [
        "wind / current direction + strength",
        "traffic flow, net migration, request routing"
      ],
      "avoidFor": [
        "exact magnitude (label it)",
        "a time series (Sparkline)"
      ],
      "props": [
        {
          "name": "direction",
          "type": "number",
          "required": true,
          "description": "Degrees; 0 = up/north, clockwise."
        },
        {
          "name": "magnitude",
          "type": "number",
          "required": true,
          "description": "Any unit; quantized into barbs."
        },
        {
          "name": "step",
          "type": "number",
          "required": false,
          "description": "Full-barb quantum (each barb = step)."
        },
        {
          "name": "label",
          "type": "\"value\" | \"none\"",
          "required": false,
          "description": "Numeric magnitude beside the glyph."
        },
        {
          "name": "mode",
          "type": "\"barb\" | \"arrow\"",
          "required": false,
          "description": "\"arrow\" swaps quantized barbs for a plain direction arrow + label."
        }
      ],
      "examples": [
        {
          "title": "Wind",
          "code": "import { WindBarb } from \"@microcharts/react/wind-barb\";\n\n<WindBarb direction={225} magnitude={32} step={10} title=\"Wind\" />"
        }
      ]
    },
    {
      "name": "StarSpoke",
      "slug": "star-spoke",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/star-spoke",
      "staticImport": "@microcharts/react/star-spoke",
      "interactiveImport": "@microcharts/react/star-spoke/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value }[] (3–8 metrics)",
      "primaryEncoding": "spoke length from center = value",
      "bestFor": [
        "entity profiles in small multiples",
        "skill / capability comparison"
      ],
      "avoidFor": [
        "fewer than 3 metrics (PairedBars)",
        "precise values (MiniBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label, value }[]",
          "required": true,
          "description": "3–8 metrics on a shared domain."
        },
        {
          "name": "dots",
          "type": "\"tips\" | \"none\"",
          "required": false,
          "description": "`\"tips\"` draws endpoint dots to sharpen the outlier read."
        },
        {
          "name": "guides",
          "type": "boolean",
          "required": false,
          "description": "Full-length guide spokes (read-back scaffold)."
        },
        {
          "name": "compare",
          "type": "number[]",
          "required": false,
          "description": "Muted ghost baseline spokes."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Spoke labels at the tips (default true; drop out below size 44)."
        }
      ],
      "examples": [
        {
          "title": "Product profile",
          "code": "import { StarSpoke } from \"@microcharts/react/star-spoke\";\n\n<StarSpoke data={metrics} title=\"Product profile\" />"
        }
      ]
    },
    {
      "name": "MinimapStrip",
      "slug": "minimap-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/minimap-strip",
      "staticImport": "@microcharts/react/minimap-strip",
      "interactiveImport": "@microcharts/react/minimap-strip/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate"
      ],
      "dataShape": "{ content, window, marks?, known? }",
      "primaryEncoding": "position (window + marks along the extent)",
      "bestFor": [
        "document / log position",
        "long-timeline navigation"
      ],
      "avoidFor": [
        "a single value (Progress)",
        "exact content values (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ content, window, marks?, known? }",
          "required": true,
          "description": "Density series, viewport, ticks, covered regions."
        },
        {
          "name": "mode",
          "type": "\"bars\" | \"heat\"",
          "required": false,
          "description": "Heat is a calmer opacity strip."
        },
        {
          "name": "markLane",
          "type": "boolean",
          "required": false,
          "description": "Dedicated tick lane vs overlaying ticks."
        },
        {
          "name": "onWindowChange",
          "type": "(window: [number, number]) => void",
          "required": false,
          "description": "Fires with the new `[start, end]` index range as the brush window is dragged.",
          "interactive": true
        }
      ],
      "examples": [
        {
          "title": "Document position",
          "code": "import { MinimapStrip } from \"@microcharts/react/minimap-strip\";\n\n<MinimapStrip\n  data={{\n    content: Array.from(\n      { length: 1200 },\n      (_, i) => Math.abs(Math.sin(i / 40)) + Math.abs(Math.sin(i / 150)) * 0.6,\n    ),\n    window: [520, 660],\n    marks: [100, 600, 1100],\n    known: [[0, 1104]],\n  }}\n  title=\"Document position\"\n/>"
        }
      ]
    },
    {
      "name": "DualWindowMeter",
      "slug": "dual-window-meter",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/dual-window-meter",
      "staticImport": "@microcharts/react/dual-window-meter",
      "interactiveImport": "@microcharts/react/dual-window-meter/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[] raw series + target",
      "primaryEncoding": "two co-plotted rolling means vs a target line",
      "bestFor": [
        "loudness / LUFS metering",
        "latency SLO or CPU-headroom compliance"
      ],
      "avoidFor": [
        "a single series (Sparkline)",
        "no target to compare against"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Raw samples; two rolling means are computed."
        },
        {
          "name": "target",
          "type": "number",
          "required": true,
          "description": "The compliance line — required."
        },
        {
          "name": "windows",
          "type": "[number, number]",
          "required": false,
          "description": "Fast/slow integration windows (samples)."
        },
        {
          "name": "band",
          "type": "[number, number]",
          "required": false,
          "description": "A compliance corridor instead of one line."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Fix the vertical scale instead of auto-fitting both traces."
        }
      ],
      "examples": [
        {
          "title": "Loudness",
          "code": "import { DualWindowMeter } from \"@microcharts/react/dual-window-meter\";\n\n<DualWindowMeter\n  data={samples}\n  target={-23}\n  format={{ maximumFractionDigits: 1 }}\n  title=\"Loudness\"\n/>"
        }
      ]
    },
    {
      "name": "DepthWedge",
      "slug": "depth-wedge",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/depth-wedge",
      "staticImport": "@microcharts/react/depth-wedge",
      "interactiveImport": "@microcharts/react/depth-wedge/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ demand: { level, amount }[], supply: { level, amount }[] }",
      "primaryEncoding": "area (cumulative step-wedges)",
      "bestFor": [
        "order-book depth / liquidity",
        "supply vs demand posture"
      ],
      "avoidFor": [
        "a time series (Sparkline)",
        "a single ratio (Delta)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ demand, supply }",
          "required": true,
          "description": "Level/amount rows per side."
        },
        {
          "name": "levels",
          "type": "number",
          "required": false,
          "description": "± level distance from mid to include."
        },
        {
          "name": "normalize",
          "type": "boolean",
          "required": false,
          "description": "Plot cumulative shares per side."
        },
        {
          "name": "label",
          "type": "\"spread\" | \"none\"",
          "required": false,
          "description": "The gap is the headline number."
        }
      ],
      "examples": [
        {
          "title": "Order book",
          "code": "import { DepthWedge } from \"@microcharts/react/depth-wedge\";\n\n<DepthWedge data={{ demand, supply }} title=\"Order book\" />"
        }
      ]
    },
    {
      "name": "PartitionStrip",
      "slug": "partition-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/partition-strip",
      "staticImport": "@microcharts/react/partition-strip",
      "interactiveImport": "@microcharts/react/partition-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, value?, children? }[] (two levels)",
      "primaryEncoding": "width = share of whole, children aligned under parents",
      "bestFor": [
        "bundle / storage / budget composition",
        "two-level breakdowns"
      ],
      "avoidFor": [
        "deep hierarchies (unreadable)",
        "flat parts (SegmentedBar)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label, value?, children? }[]",
          "required": true,
          "description": "Two-level hierarchy."
        },
        {
          "name": "emphasis",
          "type": "string",
          "required": false,
          "description": "Accents one node and its lineage."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Parent-row labels with size drop-out."
        },
        {
          "name": "colors",
          "type": "string[]",
          "required": false,
          "description": "Per-group colours, cycled; overrides --mc-cat-N. Accent/neutral roles keep."
        }
      ],
      "examples": [
        {
          "title": "Bundle composition",
          "code": "import { PartitionStrip } from \"@microcharts/react/partition-strip\";\n\n<PartitionStrip data={bundle} title=\"Bundle composition\" />"
        }
      ]
    },
    {
      "name": "CalibrationStrip",
      "slug": "calibration-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/calibration-strip",
      "staticImport": "@microcharts/react/calibration-strip",
      "interactiveImport": "@microcharts/react/calibration-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ p, outcome }[] raw, or { predicted, observed, count }[] pre-binned",
      "primaryEncoding": "observed frequency vs the identity diagonal per bin",
      "bestFor": [
        "classifier reliability / trust",
        "probability-forecast auditing"
      ],
      "avoidFor": [
        "a single accuracy number (Delta)",
        "where errors go (ConfusionGrid)"
      ],
      "props": [
        {
          "name": "data",
          "type": "RawPair[] | BinnedRow[]",
          "required": true,
          "description": "Raw pairs or pre-binned reliability rows."
        },
        {
          "name": "bins",
          "type": "number",
          "required": false,
          "description": "Uniform bin count for raw input."
        },
        {
          "name": "minSupport",
          "type": "number",
          "required": false,
          "description": "Below this a bin renders low-confidence."
        },
        {
          "name": "mode",
          "type": "\"dots\" | \"bars\"",
          "required": false,
          "description": "Bars draw signed deviation columns."
        },
        {
          "name": "color",
          "type": "string",
          "required": false,
          "description": "Accent stroke/fill override."
        }
      ],
      "examples": [
        {
          "title": "Model calibration",
          "code": "import { CalibrationStrip } from \"@microcharts/react/calibration-strip\";\n\n<CalibrationStrip data={reliability} title=\"Model calibration\" />"
        }
      ]
    },
    {
      "name": "ConfusionGrid",
      "slug": "confusion-grid",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/confusion-grid",
      "staticImport": "@microcharts/react/confusion-grid",
      "interactiveImport": "@microcharts/react/confusion-grid/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ labels: string[], counts: number[][] } (k×k, k ∈ [2,4])",
      "primaryEncoding": "row-normalized cell ink; diagonal accented by shape",
      "bestFor": [
        "classifier evaluation dashboards",
        "any paired-classification agreement"
      ],
      "avoidFor": [
        "a single accuracy number (Delta)",
        "k > 4 classes (full heatmap)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ labels, counts }",
          "required": true,
          "description": "k×k matrix; rows actual, columns predicted."
        },
        {
          "name": "normalize",
          "type": "\"row\" | \"none\"",
          "required": false,
          "description": "Row = recall view (default)."
        },
        {
          "name": "accent",
          "type": "\"diagonal\" | \"errors\"",
          "required": false,
          "description": "Agreement or the worst confusion."
        },
        {
          "name": "label",
          "type": "\"accuracy\" | \"none\"",
          "required": false,
          "description": "Overall accuracy in the gutter (opt-in)."
        },
        {
          "name": "shape",
          "type": "\"square\" | \"round\"",
          "required": false,
          "description": "Cell shape from the shared vocabulary (default 'square')."
        },
        {
          "name": "color",
          "type": "string",
          "required": false,
          "description": "Accent fill override."
        }
      ],
      "examples": [
        {
          "title": "Classifier",
          "code": "import { ConfusionGrid } from \"@microcharts/react/confusion-grid\";\n\n<ConfusionGrid data={counts} title=\"Classifier\" />"
        }
      ]
    },
    {
      "name": "FoldedDayBand",
      "slug": "folded-day-band",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/folded-day-band",
      "staticImport": "@microcharts/react/folded-day-band",
      "interactiveImport": "@microcharts/react/folded-day-band/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ t, value }[] (raw observations folded by t mod period)",
      "primaryEncoding": "median line + percentile envelopes",
      "bestFor": [
        "typical-day traffic / load profiles",
        "on-call or energy capacity"
      ],
      "avoidFor": [
        "a raw time series (Sparkline)",
        "a single period (no folding)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ t, value }[]",
          "required": true,
          "description": "Raw observations across many periods."
        },
        {
          "name": "period",
          "type": "number",
          "required": false,
          "description": "Fold length (168 folds a week)."
        },
        {
          "name": "today",
          "type": "{ t, value }[]",
          "required": false,
          "description": "The current period overlaid."
        },
        {
          "name": "percentiles",
          "type": "[number, number][]",
          "required": false,
          "description": "Percentile pairs, outermost last."
        },
        {
          "name": "bins",
          "type": "number",
          "required": false,
          "description": "Fold-axis resolution (default 24)."
        }
      ],
      "examples": [
        {
          "title": "Typical day",
          "code": "import { FoldedDayBand } from \"@microcharts/react/folded-day-band\";\n\n<FoldedDayBand data={observations} today={today} title=\"Typical day\" />"
        }
      ]
    },
    {
      "name": "VolumeProfile",
      "slug": "volume-profile",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/volume-profile",
      "staticImport": "@microcharts/react/volume-profile",
      "interactiveImport": "@microcharts/react/volume-profile/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ level, weight }[] or raw levels: number[]",
      "primaryEncoding": "horizontal bar = mass at level (level axis vertical)",
      "bestFor": [
        "volume-at-price / level-of-activity",
        "load by tier"
      ],
      "avoidFor": [
        "a time series (Sparkline)",
        "when timing matters (use a trend chart)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ level, weight }[] | number[]",
          "required": true,
          "description": "Activity mass per level, or raw levels."
        },
        {
          "name": "valueArea",
          "type": "number",
          "required": false,
          "description": "Mass fraction of the shaded value area (0.7)."
        },
        {
          "name": "align",
          "type": "\"left\" | \"right\"",
          "required": false,
          "description": "Which way bars grow."
        },
        {
          "name": "label",
          "type": "\"poc\" | \"none\"",
          "required": false,
          "description": "The POC level beside the accent bar."
        },
        {
          "name": "bins",
          "type": "number",
          "required": false,
          "description": "Number of histogram bins (default 12)."
        }
      ],
      "examples": [
        {
          "title": "Volume by price",
          "code": "import { VolumeProfile } from \"@microcharts/react/volume-profile\";\n\n<VolumeProfile data={profile} title=\"Volume by price\" />"
        }
      ]
    },
    {
      "name": "PhaseTrace",
      "slug": "phase-trace",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/phase-trace",
      "staticImport": "@microcharts/react/phase-trace",
      "interactiveImport": "@microcharts/react/phase-trace/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ x, y }[] (two synchronized signals as one trajectory)",
      "primaryEncoding": "x×y trajectory; path order = time",
      "bestFor": [
        "coupled-signal phase portraits",
        "CPU×latency, inflation×unemployment"
      ],
      "avoidFor": [
        "exact values (DualSparkline)",
        "a single series (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ x, y }[]",
          "required": true,
          "description": "Two synchronized signals, time-ordered."
        },
        {
          "name": "xLabel / yLabel",
          "type": "string",
          "required": false,
          "description": "Axis names — the summary reads them."
        },
        {
          "name": "xDomain",
          "type": "[number, number]",
          "required": false,
          "description": "Fix the x-axis range (default: the data's x-extent)."
        },
        {
          "name": "domain",
          "type": "[number, number]",
          "required": false,
          "description": "Fix the y-axis range (default: the data's y-extent)."
        },
        {
          "name": "tail",
          "type": "number",
          "required": false,
          "description": "Fraction of points drawn in accent (recent motion)."
        },
        {
          "name": "grid",
          "type": "boolean",
          "required": false,
          "description": "Quadrant hairlines for regime reads."
        },
        {
          "name": "startDot",
          "type": "boolean",
          "required": false,
          "description": "Anchor the path's origin for full-journey reads (default false)."
        }
      ],
      "examples": [
        {
          "title": "CPU × latency",
          "code": "import { PhaseTrace } from \"@microcharts/react/phase-trace\";\n\n<PhaseTrace data={trajectory} xLabel=\"CPU\" yLabel=\"Latency\" title=\"Phase portrait\" />"
        }
      ]
    },
    {
      "name": "TraceFold",
      "slug": "trace-fold",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/trace-fold",
      "staticImport": "@microcharts/react/trace-fold",
      "interactiveImport": "@microcharts/react/trace-fold/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, start, duration, depth, parent?, critical? }[]",
      "primaryEncoding": "width = duration, x = start, row = depth; critical path accented",
      "bestFor": [
        "request traces / flame charts",
        "p95-exemplar latency breakdowns"
      ],
      "avoidFor": [
        "a single duration (Bullet)",
        "a time series (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "Span[]",
          "required": true,
          "description": "Flat span list; parent = index."
        },
        {
          "name": "emphasis",
          "type": "\"critical\" | \"none\"",
          "required": false,
          "description": "Mute non-critical spans, or uniform."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Width-gated in-rect labels."
        }
      ],
      "examples": [
        {
          "title": "Request trace",
          "code": "import { TraceFold } from \"@microcharts/react/trace-fold\";\n\n<TraceFold data={spans} title=\"Request trace\" />"
        }
      ]
    },
    {
      "name": "TapeGauge",
      "slug": "tape-gauge",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/tape-gauge",
      "staticImport": "@microcharts/react/tape-gauge",
      "interactiveImport": "@microcharts/react/tape-gauge/interactive",
      "picker": false,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onSelect"
      ],
      "dataShape": "value: number, rate?: number, zones?: { from, to, tone }[]",
      "primaryEncoding": "position on a moving scale = level; chevron count = rate (a separate channel)",
      "bestFor": [
        "a live changing reading (airspeed, throughput, temp)",
        "value + trend + safe/caution band at a glance"
      ],
      "avoidFor": [
        "a history you want to scan (Sparkline)",
        "a single static number (Delta)"
      ],
      "props": [
        {
          "name": "value",
          "type": "number",
          "required": true,
          "description": "The current level; parked at the pointer."
        },
        {
          "name": "rate",
          "type": "number",
          "required": false,
          "description": "Signed units/tick; drives the chevrons."
        },
        {
          "name": "zones",
          "type": "{ from, to, tone }[]",
          "required": false,
          "description": "Semantic bands on the scale."
        },
        {
          "name": "span",
          "type": "number",
          "required": false,
          "description": "Visible scale extent; fixed while live."
        },
        {
          "name": "rateTiers",
          "type": "[number, number]",
          "required": false,
          "description": "Thresholds for 1 and 2 chevrons (default [span/60, span/15])."
        },
        {
          "name": "orientation",
          "type": "\"vertical\" | \"horizontal\"",
          "required": false,
          "description": "Tape direction (default vertical)."
        },
        {
          "name": "announceEvery",
          "type": "number",
          "required": false,
          "description": "Minimum ms between live-region announcements as the value streams (default 5000).",
          "interactive": true
        }
      ],
      "examples": [
        {
          "title": "Airspeed",
          "code": "import { TapeGauge } from \"@microcharts/react/tape-gauge\";\n\n<TapeGauge value={142} rate={1} zones={zones} span={60} title=\"Airspeed\" />"
        }
      ]
    },
    {
      "name": "StationGlyph",
      "slug": "station-glyph",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/station-glyph",
      "staticImport": "@microcharts/react/station-glyph",
      "interactiveImport": "@microcharts/react/station-glyph/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "cloud, wind{ direction, magnitude }, temp, dewpoint, pressure, station",
      "primaryEncoding": "disc fill = sky cover; barb = wind; corner numerals = temp / dew / pressure",
      "bestFor": [
        "a dense weather station model",
        "any multi-field reading that must fit one cell"
      ],
      "avoidFor": [
        "a single value (Delta)",
        "a trend over time (Sparkline)"
      ],
      "props": [
        {
          "name": "cloud",
          "type": "number",
          "required": false,
          "description": "Sky cover 0–1; fills the disc."
        },
        {
          "name": "wind",
          "type": "{ direction, magnitude }",
          "required": false,
          "description": "Barb direction + speed."
        },
        {
          "name": "step",
          "type": "number",
          "required": false,
          "description": "Wind-barb quantum — each full barb (default 10)."
        },
        {
          "name": "temp",
          "type": "number",
          "required": false,
          "description": "Upper-left numeral."
        },
        {
          "name": "dewpoint",
          "type": "number",
          "required": false,
          "description": "Lower-left numeral."
        },
        {
          "name": "pressure",
          "type": "number",
          "required": false,
          "description": "Upper-right numeral."
        },
        {
          "name": "station",
          "type": "string",
          "required": false,
          "description": "Top-left identifier."
        }
      ],
      "examples": [
        {
          "title": "Station model",
          "code": "import { StationGlyph } from \"@microcharts/react/station-glyph\";\n\n<StationGlyph\n  station=\"KSFO\"\n  cloud={0.75}\n  wind={{ direction: 225, magnitude: 15 }}\n  temp={16}\n  dewpoint={9}\n  pressure={1013}\n/>"
        }
      ]
    },
    {
      "name": "CohortTriangle",
      "slug": "cohort-triangle",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/cohort-triangle",
      "staticImport": "@microcharts/react/cohort-triangle",
      "interactiveImport": "@microcharts/react/cohort-triangle/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ label, values }[], retention per age (ragged rows)",
      "primaryEncoding": "color intensity (discrete levels) over an age × cohort grid",
      "bestFor": [
        "monthly/weekly cohorts side by side",
        "spotting which vintage decays worst",
        "equal-maturity retention in a KPI card"
      ],
      "avoidFor": [
        "exact per-cell values",
        "a single cohort curve (RetentionCurve)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ label, values }[]",
          "required": true,
          "description": "One row per cohort; values[i] = retention at age i (0–1 or 0–100, ragged)."
        },
        {
          "name": "labels",
          "type": "boolean",
          "required": false,
          "description": "Cohort labels in a left gutter (default true; drops at tiny cell sizes)."
        },
        {
          "name": "highlight",
          "type": "string",
          "required": false,
          "description": "Ring the cohort with this label — the comparison focus."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Age-column noun for the summary (default \"period\")."
        },
        {
          "name": "cell",
          "type": "number",
          "required": false,
          "description": "Cell edge length in viewBox units."
        },
        {
          "name": "title",
          "type": "string",
          "required": false,
          "description": "Accessible name; joins the auto summary."
        },
        {
          "name": "summary",
          "type": "string | false",
          "required": false,
          "description": "Override or disable the auto summary."
        }
      ],
      "examples": [
        {
          "title": "Monthly retention cohorts",
          "code": "import { CohortTriangle } from \"@microcharts/react/cohort-triangle\";\n\n<CohortTriangle data={cohorts} unit=\"month\" title=\"Monthly retention\" />"
        }
      ]
    },
    {
      "name": "StreakSpark",
      "slug": "streak-spark",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/streak-spark",
      "staticImport": "@microcharts/react/streak-spark",
      "interactiveImport": "@microcharts/react/streak-spark/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "(boolean | number | null)[]",
      "primaryEncoding": "width = run length; height + opacity = run type; current run accented",
      "bestFor": [
        "pass/fail run histories",
        "uptime & incident-free streaks",
        "current vs record streaks"
      ],
      "avoidFor": [
        "a continuous magnitude (SparkBar)",
        "a single ratio (Progress)"
      ],
      "props": [
        {
          "name": "data",
          "type": "(boolean | number | null)[]",
          "required": true,
          "description": "Outcomes; null is a gap that breaks the run. Numbers pass on > 0."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Which outcome is the streak: pass (up) or fail (down)."
        },
        {
          "name": "threshold",
          "type": "number",
          "required": false,
          "description": "With numeric data, values ≥ threshold pass."
        },
        {
          "name": "label",
          "type": "\"current\" | \"both\" | \"none\"",
          "required": false,
          "description": "Count labels: the current run, the record too, or neither."
        },
        {
          "name": "title",
          "type": "string",
          "required": false,
          "description": "Accessible name; joins the auto summary."
        },
        {
          "name": "summary",
          "type": "string | false",
          "required": false,
          "description": "Override or disable the auto summary."
        }
      ],
      "examples": [
        {
          "title": "Deploy streak",
          "code": "import { StreakSpark } from \"@microcharts/react/streak-spark\";\n\n// 1 = passing build, 0 = failing build\n<StreakSpark\n  data={[1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1]}\n  title=\"Deploy streak\"\n/>"
        }
      ]
    },
    {
      "name": "GradeProfile",
      "slug": "grade-profile",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/grade-profile",
      "staticImport": "@microcharts/react/grade-profile",
      "interactiveImport": "@microcharts/react/grade-profile/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ d, elev }[], distance + elevation in the same unit",
      "primaryEncoding": "colour = quantized grade bin; area = elevation ridge; x = distance",
      "bestFor": [
        "route / climb profiles (cycling, running, hiking)",
        "where the hard pitches fall"
      ],
      "avoidFor": [
        "a single elevation series (Sparkline)",
        "non-monotone tracks (needs distance order)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ d: number; elev: number }[]",
          "required": true,
          "description": "Distance + elevation, monotonic in d, same unit so grade is a true percent."
        },
        {
          "name": "bins",
          "type": "[number, number, number]",
          "required": false,
          "description": "Ascending grade-% thresholds (always percent) that quantize the four difficulty bins."
        },
        {
          "name": "format",
          "type": "Intl.NumberFormatOptions | (n) => string",
          "required": false,
          "description": "Formats distance and elevation in the summary and readout; grades always render as percent."
        },
        {
          "name": "label",
          "type": "\"max\" | \"none\"",
          "required": false,
          "description": "Mark the steepest pitch, or render the profile alone."
        }
      ],
      "examples": [
        {
          "title": "Queen stage",
          "code": "import { GradeProfile } from \"@microcharts/react/grade-profile\";\n\n<GradeProfile data={trail} format={(n) => `${n} m`} title=\"Queen stage\" />"
        }
      ]
    },
    {
      "name": "WinProbWorm",
      "slug": "win-prob-worm",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/win-prob-worm",
      "staticImport": "@microcharts/react/win-prob-worm",
      "interactiveImport": "@microcharts/react/win-prob-worm/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[]",
      "primaryEncoding": "y = win probability on a fixed 0–100 axis, split at the 50% line",
      "bestFor": [
        "live win / election probability where the lead flips",
        "a modelled forecast whose crossings are the story",
        "any 0–100 probability you must not truncate"
      ],
      "avoidFor": [
        "a raw score or margin (Sparkline)",
        "a value that isn't a bounded 0–100 probability"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "A single win-probability series, clamped to 0–100."
        },
        {
          "name": "sides",
          "type": "[string, string]",
          "required": false,
          "description": "Names for the two sides — [>50, <50]. Default [\"A\", \"B\"]."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Print the current leader's probability at the endpoint (default \"last\")."
        },
        {
          "name": "markSwing",
          "type": "boolean",
          "required": false,
          "description": "Mark the biggest momentum swing (default true; seat-gated)."
        }
      ],
      "examples": [
        {
          "title": "Win probability",
          "code": "import { WinProbWorm } from \"@microcharts/react/win-prob-worm\";\n\n<WinProbWorm\n  data={[50, 48, 45, 52, 60, 58, 42, 38, 55, 68, 82, 90, 88, 94, 98]}\n  sides={[\"home\", \"away\"]}\n  title=\"Win probability\"\n/>"
        }
      ]
    },
    {
      "name": "QueueDepth",
      "slug": "queue-depth",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/queue-depth",
      "staticImport": "@microcharts/react/queue-depth",
      "interactiveImport": "@microcharts/react/queue-depth/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[], backlog depth per period (≥ 0)",
      "primaryEncoding": "zero-anchored area (stock) + above-capacity spans re-stroked negative",
      "bestFor": [
        "a support-queue backlog in a KPI card",
        "a work-in-progress stock vs its WIP limit",
        "will-it-drain in a tab header"
      ],
      "avoidFor": [
        "a rate rather than a stock (Sparkline)",
        "a single count (Delta)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Backlog depth per period (≥ 0). null / NaN / ±Infinity are gaps."
        },
        {
          "name": "capacity",
          "type": "number",
          "required": false,
          "description": "Steady-state capacity: a dashed hairline; spans above it re-stroke negative."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Endpoint value + trend glyph (▴/▾), default 'last', or nothing."
        }
      ],
      "examples": [
        {
          "title": "Support queue",
          "code": "import { QueueDepth } from \"@microcharts/react/queue-depth\";\n\n<QueueDepth\n  data={[42, 55, 70, 88, 96, 120, 150, 182, 214]}\n  capacity={100}\n  title=\"Support queue\"\n/>"
        }
      ]
    },
    {
      "name": "SpreadBand",
      "slug": "spread-band",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/spread-band",
      "staticImport": "@microcharts/react/spread-band",
      "interactiveImport": "@microcharts/react/spread-band/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "data: { a, b }[], a = subject, b = reference (null in either = gap in both)",
      "primaryEncoding": "signed area between two lines on ONE shared scale, split at crossings",
      "bestFor": [
        "lead-vs-reference in KPI cards",
        "actual-vs-plan where the flip matters"
      ],
      "avoidFor": [
        "3+ series (SparkGroup)",
        "unpaired series or different units (never dual axes)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ a: number | null; b: number | null }[]",
          "required": true,
          "description": "Paired readings — a is the subject, b the reference."
        },
        {
          "name": "seriesLabels",
          "type": "[string, string]",
          "required": false,
          "description": "Names the two series in the summary and label."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Which lead is the good valence; down flips the fill colors."
        },
        {
          "name": "label",
          "type": "\"gap\" | \"none\"",
          "required": false,
          "description": "Current signed gap in a right gutter (default gap)."
        }
      ],
      "examples": [
        {
          "title": "Organic vs paid",
          "code": "import { SpreadBand } from \"@microcharts/react/spread-band\";\n\n<SpreadBand data={pairs} seriesLabels={[\"Organic\", \"Paid\"]} title=\"Organic vs paid\" />"
        }
      ]
    },
    {
      "name": "BiasStrip",
      "slug": "bias-strip",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/bias-strip",
      "staticImport": "@microcharts/react/bias-strip",
      "interactiveImport": "@microcharts/react/bias-strip/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "{ a, b }[] (paired measurements)",
      "primaryEncoding": "vertical position of the paired difference",
      "bestFor": [
        "method-agreement checks in a cell",
        "instrument drift in a KPI card"
      ],
      "avoidFor": [
        "unpaired samples (MicroScatter)",
        "a single time series (Sparkline)"
      ],
      "props": [
        {
          "name": "data",
          "type": "{ a; b }[]",
          "required": true,
          "description": "Paired measurements."
        },
        {
          "name": "limits",
          "type": "number",
          "required": false,
          "description": "k in bias ± k·σ (default 1.96 ≈ 95% limits of agreement)."
        },
        {
          "name": "label",
          "type": "\"bias\" | \"none\"",
          "required": false,
          "description": "Seat-gated bias caption (default) or hidden."
        },
        {
          "name": "r",
          "type": "number",
          "required": false,
          "description": "Base dot radius, clamped [1, 3]."
        }
      ],
      "examples": [
        {
          "title": "Device vs reference",
          "code": "import { BiasStrip } from \"@microcharts/react/bias-strip\";\n\n<BiasStrip data={pairs} title=\"Device vs reference\" />"
        }
      ]
    },
    {
      "name": "PercentileTrace",
      "slug": "percentile-trace",
      "status": "stable",
      "docs": "https://microcharts.dev/docs/charts/percentile-trace",
      "staticImport": "@microcharts/react/percentile-trace",
      "interactiveImport": "@microcharts/react/percentile-trace/interactive",
      "picker": true,
      "animates": true,
      "sharedInteractive": [
        "animate",
        "onActive",
        "onSelect",
        "selectedIndex",
        "defaultSelectedIndex",
        "readout"
      ],
      "dataShape": "number[], percentile ranks 0–100, one per reading",
      "primaryEncoding": "line position on a locked 0–100 percentile scale",
      "bestFor": [
        "one player's or product's rank drifting over time",
        "whether a standing has crossed into the top or bottom of the pack",
        "a percentile KPI where the population context matters"
      ],
      "avoidFor": [
        "a raw value over time (Sparkline)",
        "one absolute number vs a target (Bullet / Delta)"
      ],
      "props": [
        {
          "name": "data",
          "type": "number[]",
          "required": true,
          "description": "Percentile ranks 0–100, one per reading; out-of-range values are clamped."
        },
        {
          "name": "showBands",
          "type": "boolean",
          "required": false,
          "description": "Draw the fixed p25–75 and p5–95 population fields (default true)."
        },
        {
          "name": "positive",
          "type": "\"up\" | \"down\"",
          "required": false,
          "description": "Which direction is good — colors the endpoint dot (default up)."
        },
        {
          "name": "label",
          "type": "\"last\" | \"none\"",
          "required": false,
          "description": "Final percentile in a right gutter."
        },
        {
          "name": "unit",
          "type": "string",
          "required": false,
          "description": "Reading noun for the interactive announcement (default 'step').",
          "interactive": true
        }
      ],
      "examples": [
        {
          "title": "Standing",
          "code": "import { PercentileTrace } from \"@microcharts/react/percentile-trace\";\n\n<PercentileTrace data={ranks} title=\"Standing\" />"
        }
      ]
    }
  ]
}