{
  "schema": 1,
  "version": "0.8.0",
  "reflex": {
    "version": "0.7.1",
    "wraps": "0.7.0",
    "stale": true
  },
  "frameworks": [
    "react",
    "vue",
    "angular",
    "reflex"
  ],
  "families": [
    {
      "slug": "lines",
      "title": "Lines"
    },
    {
      "slug": "bars",
      "title": "Bars"
    },
    {
      "slug": "areas",
      "title": "Areas"
    },
    {
      "slug": "points-grids",
      "title": "Points & grids"
    },
    {
      "slug": "flows",
      "title": "Flows"
    },
    {
      "slug": "radial",
      "title": "Radial"
    },
    {
      "slug": "distributions-comparisons",
      "title": "Distributions & comparisons"
    },
    {
      "slug": "hierarchies-dimensions",
      "title": "Hierarchies & dimensions"
    },
    {
      "slug": "fields-networks",
      "title": "Fields & networks"
    }
  ],
  "common": {
    "chart": [
      {
        "name": "data",
        "reflex": "data",
        "type": "readonly Datum[]",
        "optional": true,
        "doc": "Rows to draw. If omitted, the demo dataset is rendered (REQ-093): accessor props (`…Key`, `keys`, `names`, `levels`, `axis`, `dimensions`, `period`, `nodes`) are ignored, every other prop applies."
      },
      {
        "name": "ground",
        "reflex": "ground",
        "type": "GroundRef",
        "optional": true,
        "default": "'silverpoint'",
        "doc": "Style ground. Defaults to the app provider's, or `silverpoint`."
      },
      {
        "name": "substrate",
        "reflex": "substrate",
        "type": "SubstrateName",
        "optional": true,
        "default": "'cream'",
        "doc": "Prepared substrate within the ground (REQ-046)."
      },
      {
        "name": "mode",
        "reflex": "mode",
        "type": "InkMode",
        "optional": true,
        "default": "'ink'",
        "doc": "`ink` by default; `precision` disables inking (REQ-021)."
      },
      {
        "name": "palette",
        "reflex": "palette",
        "type": "Palette",
        "optional": true,
        "doc": "Colours over the ground's, field by field, written on the root's `style` (REQ-461). Merged over the dashboard's and the provider's (REQ-462); presets are on `@silverpoint/core/palettes`."
      },
      {
        "name": "seed",
        "reflex": "seed",
        "type": "Seed",
        "optional": true,
        "doc": "Seed. If omitted, it is derived from `id` stably (REQ-003)."
      },
      {
        "name": "id",
        "reflex": "id",
        "type": "string",
        "optional": true,
        "doc": "Stable identifier. If omitted, it is generated deterministically."
      },
      {
        "name": "height",
        "reflex": "height",
        "type": "number",
        "optional": true,
        "default": "160",
        "doc": "Height of the drawing area in px. Width is the container's unless pinned."
      },
      {
        "name": "width",
        "reflex": "width",
        "type": "number",
        "optional": true,
        "doc": ""
      },
      {
        "name": "chrome",
        "reflex": "chrome",
        "type": "'card' | 'bare'",
        "optional": true,
        "default": "'card'",
        "doc": "`card` draws the full frame; `bare` only the drawing area (REQ-095)."
      },
      {
        "name": "hatchFill",
        "reflex": "hatch_fill",
        "type": "'tile' | 'per-shape'",
        "optional": true,
        "default": "'tile'",
        "doc": "How areas are filled (REQ-029)."
      },
      {
        "name": "title",
        "reflex": "title",
        "type": "string",
        "optional": true,
        "doc": ""
      },
      {
        "name": "badge",
        "reflex": "badge",
        "type": "string",
        "optional": true,
        "doc": ""
      },
      {
        "name": "value",
        "reflex": "value",
        "type": "string | number",
        "optional": true,
        "doc": ""
      },
      {
        "name": "unit",
        "reflex": "unit",
        "type": "string",
        "optional": true,
        "doc": ""
      },
      {
        "name": "footerLeft",
        "reflex": "footer_left",
        "type": "string",
        "optional": true,
        "doc": ""
      },
      {
        "name": "footerRight",
        "reflex": "footer_right",
        "type": "string",
        "optional": true,
        "doc": ""
      },
      {
        "name": "label",
        "reflex": "label",
        "type": "string",
        "optional": true,
        "doc": "Accessible name. If omitted, it is derived from `title` (REQ-120)."
      },
      {
        "name": "description",
        "reflex": "description",
        "type": "string",
        "optional": true,
        "doc": "Long description for screen readers (REQ-120)."
      },
      {
        "name": "dataTable",
        "reflex": "data_table",
        "type": "'visible' | 'hidden' | 'none'",
        "optional": true,
        "default": "'hidden'",
        "doc": "Tabular alternative; `hidden` leaves it for assistive technology only (REQ-121)."
      },
      {
        "name": "locale",
        "reflex": "locale",
        "type": "string",
        "optional": true,
        "doc": ""
      },
      {
        "name": "numberFormat",
        "reflex": "number_format",
        "type": "Intl.NumberFormatOptions",
        "optional": true,
        "doc": ""
      },
      {
        "name": "className",
        "reflex": "class_name",
        "type": "string",
        "optional": true,
        "doc": ""
      }
    ],
    "ui": [
      {
        "name": "id",
        "type": "string",
        "optional": true,
        "doc": "The frame variant and every related id derive from it (REQ-307, REQ-329)."
      },
      {
        "name": "seed",
        "reflex": "seed",
        "type": "Seed",
        "optional": true,
        "doc": "Overrides `id` for the frame variant only."
      },
      {
        "name": "ground",
        "reflex": "ground",
        "type": "GroundRef",
        "optional": true,
        "default": "'silverpoint'",
        "doc": "Style ground. Defaults to the dashboard's, then the app provider's, or `silverpoint` (REQ-311)."
      },
      {
        "name": "substrate",
        "reflex": "substrate",
        "type": "SubstrateName",
        "optional": true,
        "default": "'cream'",
        "doc": "Prepared substrate within the ground (REQ-046)."
      },
      {
        "name": "mode",
        "reflex": "mode",
        "type": "InkMode",
        "optional": true,
        "default": "'ink'",
        "doc": "`ink` by default; `precision` disables inking (REQ-021, REQ-306)."
      },
      {
        "name": "palette",
        "reflex": "palette",
        "type": "Palette",
        "optional": true,
        "doc": "Colours over the ground's, merged over the dashboard's and the provider's (REQ-461, REQ-462)."
      },
      {
        "name": "size",
        "reflex": "size",
        "type": "UiSize",
        "optional": true,
        "default": "'md'",
        "doc": "Default `'md'`."
      },
      {
        "name": "className",
        "type": "string",
        "optional": true,
        "doc": "Added to the component's root element, after its own classes."
      }
    ]
  },
  "charts": [
    {
      "slug": "line-chart",
      "names": {
        "react": "LineChart",
        "vue": "SpLineChart",
        "angular": "sp-line-chart",
        "reflex": "line_chart"
      },
      "imports": {
        "react": "@silverpoint/react/line-chart",
        "vue": "@silverpoint/vue/line-chart",
        "angular": "@silverpoint/angular/line-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "lines",
      "summary": "Spline with an optional dotted baseline series.",
      "data": {
        "shape": "series",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          },
          {
            "role": "secondary",
            "prop": "secondaryKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "trend",
        "change",
        "compare"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "secondaryKey",
          "reflex": "secondary_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "curve",
          "reflex": "curve",
          "type": "LineCurve",
          "optional": true,
          "default": "'monotone'",
          "doc": ""
        },
        {
          "name": "series",
          "reflex": "series",
          "type": "'all' | 'primary'",
          "optional": true,
          "default": "'all'",
          "doc": "`all` draws the secondary series when there is one; `primary` omits it."
        },
        {
          "name": "connectNulls",
          "reflex": "connect_nulls",
          "type": "boolean",
          "optional": true,
          "default": "false",
          "doc": "Whether a gap left by a missing value is bridged (REQ-008)."
        }
      ],
      "demo": "LINE_CHART_DEMO",
      "demoKeys": {
        "xKey": "hour",
        "valueKey": "hits",
        "secondaryKey": "baseline"
      },
      "demoSample": [
        {
          "hour": "00",
          "hits": 18,
          "baseline": 22
        },
        {
          "hour": "02",
          "hits": 14,
          "baseline": 18
        },
        {
          "hour": "04",
          "hits": 11,
          "baseline": 15
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "bullet-chart",
      "names": {
        "react": "BulletChart",
        "vue": "SpBulletChart",
        "angular": "sp-bullet-chart",
        "reflex": "bullet_chart"
      },
      "imports": {
        "react": "@silverpoint/react/bullet-chart",
        "vue": "@silverpoint/vue/bullet-chart",
        "angular": "@silverpoint/angular/bullet-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "bars",
      "summary": "One bar per target, with a marker at the target. Values in 0-100.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "title",
            "prop": "titleKey",
            "type": "string",
            "required": true
          },
          {
            "role": "actual",
            "prop": "actualKey",
            "type": "number",
            "required": true
          },
          {
            "role": "target",
            "prop": "targetKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "progress",
        "kpi",
        "compare"
      ],
      "props": [
        {
          "name": "titleKey",
          "reflex": "title_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'title'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "actualKey",
          "reflex": "actual_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'actual'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "targetKey",
          "reflex": "target_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'target'",
          "doc": "Ignored without `data`."
        }
      ],
      "demo": "BULLET_CHART_DEMO",
      "demoSample": [
        {
          "title": "Revenue",
          "actual": 72,
          "target": 80
        },
        {
          "title": "Profit",
          "actual": 58,
          "target": 65
        },
        {
          "title": "New users",
          "actual": 86,
          "target": 75
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "pyramid-chart",
      "names": {
        "react": "PyramidChart",
        "vue": "SpPyramidChart",
        "angular": "sp-pyramid-chart",
        "reflex": "pyramid_chart"
      },
      "imports": {
        "react": "@silverpoint/react/pyramid-chart",
        "vue": "@silverpoint/vue/pyramid-chart",
        "angular": "@silverpoint/angular/pyramid-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "bars",
      "summary": "Stacked tiers whose width encodes the value (0-100).",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": true
          },
          {
            "role": "width",
            "prop": "widthKey",
            "type": "number",
            "required": true
          },
          {
            "role": "tone",
            "prop": "toneKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "rank",
        "compare"
      ],
      "props": [
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'label'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "widthKey",
          "reflex": "width_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'width'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "toneKey",
          "reflex": "tone_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        }
      ],
      "demo": "PYRAMID_CHART_DEMO",
      "demoSample": [
        {
          "label": "Leads",
          "width": 18
        },
        {
          "label": "Managers",
          "width": 42
        },
        {
          "label": "Specialists",
          "width": 70
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "heatmap-chart",
      "names": {
        "react": "HeatmapChart",
        "vue": "SpHeatmapChart",
        "angular": "sp-heatmap-chart",
        "reflex": "heatmap_chart"
      },
      "imports": {
        "react": "@silverpoint/react/heatmap-chart",
        "vue": "@silverpoint/vue/heatmap-chart",
        "angular": "@silverpoint/angular/heatmap-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "points-grids",
      "summary": "Labelled rows of values, normalised against `scaleMax`.",
      "data": {
        "shape": "matrix",
        "fields": [
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": true
          },
          {
            "role": "values",
            "prop": "valuesKey",
            "type": "array",
            "required": true
          }
        ]
      },
      "intents": [
        "compare",
        "distribution"
      ],
      "props": [
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'label'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valuesKey",
          "reflex": "values_key",
          "type": "Accessor<readonly (number | null)[] | null | undefined>",
          "optional": true,
          "default": "'values'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "scaleMax",
          "reflex": "scale_max",
          "type": "number",
          "optional": true,
          "default": "100",
          "doc": "Value that maps to the darkest tone; 100 by default."
        },
        {
          "name": "columnLabels",
          "reflex": "column_labels",
          "type": "readonly string[]",
          "optional": true,
          "doc": "Names of the columns, in order; missing ones fall back to `#k` (delta-006)."
        }
      ],
      "demo": "HEATMAP_CHART_DEMO",
      "demoSample": [
        {
          "label": "Mon",
          "values": [
            12,
            34,
            58,
            71,
            66,
            40
          ]
        },
        {
          "label": "Tue",
          "values": [
            18,
            42,
            77,
            88,
            70,
            35
          ]
        },
        {
          "label": "Wed",
          "values": [
            9,
            38,
            64,
            93,
            81,
            47
          ]
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "treemap-chart",
      "names": {
        "react": "TreemapChart",
        "vue": "SpTreemapChart",
        "angular": "sp-treemap-chart",
        "reflex": "treemap_chart"
      },
      "imports": {
        "react": "@silverpoint/react/treemap-chart",
        "vue": "@silverpoint/vue/treemap-chart",
        "angular": "@silverpoint/angular/treemap-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "points-grids",
      "summary": "Tiles of `cols × rows` cells placed in a `columns × rows` grid.",
      "data": {
        "shape": "parts",
        "fields": [
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": true
          },
          {
            "role": "share",
            "prop": "shareKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "part-to-whole"
      ],
      "props": [
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'label'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "shareKey",
          "reflex": "share_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'share'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "columns",
          "reflex": "columns",
          "type": "number",
          "optional": true,
          "doc": ""
        },
        {
          "name": "rows",
          "reflex": "rows",
          "type": "number",
          "optional": true,
          "doc": ""
        }
      ],
      "demo": "TREEMAP_CHART_DEMO",
      "demoSample": [
        {
          "label": "Search",
          "share": 48,
          "cols": 3,
          "rows": 4
        },
        {
          "label": "Direct",
          "share": 26,
          "cols": 3,
          "rows": 2
        },
        {
          "label": "Social",
          "share": 17,
          "cols": 2,
          "rows": 2
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "sankey-chart",
      "names": {
        "react": "SankeyChart",
        "vue": "SpSankeyChart",
        "angular": "sp-sankey-chart",
        "reflex": "sankey_chart"
      },
      "imports": {
        "react": "@silverpoint/react/sankey-chart",
        "vue": "@silverpoint/vue/sankey-chart",
        "angular": "@silverpoint/angular/sankey-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "flows",
      "summary": "Flow bands between layered nodes.",
      "data": {
        "shape": "links",
        "fields": [
          {
            "role": "source",
            "prop": "sourceKey",
            "type": "string",
            "required": true
          },
          {
            "role": "target",
            "prop": "targetKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "flow",
        "part-to-whole"
      ],
      "props": [
        {
          "name": "sourceKey",
          "reflex": "source_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'source'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "targetKey",
          "reflex": "target_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'target'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        }
      ],
      "demo": "SANKEY_CHART_DEMO",
      "demoSample": [
        {
          "source": "Search",
          "target": "Visit",
          "value": 48
        },
        {
          "source": "Social",
          "target": "Visit",
          "value": 27
        },
        {
          "source": "Email",
          "target": "Visit",
          "value": 15
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "activity-grid",
      "names": {
        "react": "ActivityGrid",
        "vue": "SpActivityGrid",
        "angular": "sp-activity-grid",
        "reflex": "activity_grid"
      },
      "imports": {
        "react": "@silverpoint/react/activity-grid",
        "vue": "@silverpoint/vue/activity-grid",
        "angular": "@silverpoint/angular/activity-grid",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "points-grids",
      "summary": "One cell per day, a column per week.",
      "data": {
        "shape": "events",
        "fields": [
          {
            "role": "date",
            "prop": "dateKey",
            "type": "date",
            "required": true
          },
          {
            "role": "count",
            "prop": "countKey",
            "type": "number",
            "required": false
          },
          {
            "role": "level",
            "prop": "levelKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "schedule",
        "trend"
      ],
      "props": [
        {
          "name": "dateKey",
          "reflex": "date_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'date'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "countKey",
          "reflex": "count_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'count'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "levelKey",
          "reflex": "level_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'level'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "weeks",
          "reflex": "weeks",
          "type": "number",
          "optional": true,
          "default": "26",
          "doc": "Weeks shown, the most recent last; 26 by default."
        }
      ],
      "demo": "ACTIVITY_GRID_DEMO",
      "demoSample": [
        {
          "date": "2025-12-31",
          "count": 1,
          "level": 1
        },
        {
          "date": "2026-01-01",
          "count": 0,
          "level": 0
        },
        {
          "date": "2026-01-02",
          "count": 4,
          "level": 2
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "step-chart",
      "names": {
        "react": "StepChart",
        "vue": "SpStepChart",
        "angular": "sp-step-chart",
        "reflex": "step_chart"
      },
      "imports": {
        "react": "@silverpoint/react/step-chart",
        "vue": "@silverpoint/vue/step-chart",
        "angular": "@silverpoint/angular/step-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "lines",
      "summary": "A series drawn as steps.",
      "data": {
        "shape": "series",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "trend",
        "change"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "step",
          "reflex": "step",
          "type": "'after' | 'before' | 'middle'",
          "optional": true,
          "default": "'after'",
          "doc": "Where the step sits between two points; `after` by default."
        }
      ],
      "demo": "STEP_CHART_DEMO",
      "demoSample": [
        {
          "x": "Jan",
          "value": 12
        },
        {
          "x": "Feb",
          "value": 12
        },
        {
          "x": "Mar",
          "value": 18
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "sparkline-rows",
      "names": {
        "react": "SparklineRows",
        "vue": "SpSparklineRows",
        "angular": "sp-sparkline-rows",
        "reflex": "sparkline_rows"
      },
      "imports": {
        "react": "@silverpoint/react/sparkline-rows",
        "vue": "@silverpoint/vue/sparkline-rows",
        "angular": "@silverpoint/angular/sparkline-rows",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "lines",
      "summary": "One row per series — name, sparkline, readout.",
      "data": {
        "shape": "series",
        "fields": [
          {
            "role": "name",
            "prop": "nameKey",
            "type": "string",
            "required": true
          },
          {
            "role": "points",
            "prop": "seriesKey",
            "type": "array",
            "required": true
          },
          {
            "role": "point",
            "prop": "pointKey",
            "type": "number",
            "required": false
          },
          {
            "role": "readout",
            "prop": "readoutKey",
            "type": "string",
            "required": false
          }
        ]
      },
      "intents": [
        "trend",
        "compare",
        "kpi"
      ],
      "props": [
        {
          "name": "rows",
          "reflex": "rows",
          "type": "number",
          "optional": true,
          "doc": "Rows shown, from the first; all by default."
        },
        {
          "name": "nameKey",
          "reflex": "name_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'name'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "readoutKey",
          "reflex": "readout_key",
          "type": "Accessor<string | number | null | undefined>",
          "optional": true,
          "default": "'readout'",
          "doc": "The printed readout; the last value of the series by default. Ignored without `data`."
        },
        {
          "name": "seriesKey",
          "reflex": "series_key",
          "type": "Accessor<readonly unknown[] | null | undefined>",
          "optional": true,
          "default": "'points'",
          "doc": "The row's points: an array. Ignored without `data`."
        },
        {
          "name": "pointKey",
          "reflex": "point_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "The value of one point; the point itself when it is a number, else its `value`. Ignored without `data`."
        }
      ],
      "demo": "SPARKLINE_ROWS_DEMO",
      "demoSample": [
        {
          "name": "API",
          "readout": "99.9%",
          "points": [
            98,
            99,
            99,
            97,
            99,
            100,
            99,
            100
          ]
        },
        {
          "name": "Queue",
          "points": [
            12,
            18,
            15,
            22,
            19,
            25,
            21,
            17
          ]
        },
        {
          "name": "Cache",
          "readout": "84%",
          "points": [
            70,
            72,
            78,
            75,
            80,
            83,
            81,
            84
          ]
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "kpi-card",
      "names": {
        "react": "KpiCard",
        "vue": "SpKpiCard",
        "angular": "sp-kpi-card",
        "reflex": "kpi_card"
      },
      "imports": {
        "react": "@silverpoint/react/kpi-card",
        "vue": "@silverpoint/vue/kpi-card",
        "angular": "@silverpoint/angular/kpi-card",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "lines",
      "summary": "A metric, its delta, and an area sparkline of the series.",
      "data": {
        "shape": "single",
        "fields": [
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "kpi",
        "change"
      ],
      "props": [
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "metric",
          "reflex": "metric",
          "type": "string",
          "optional": true,
          "doc": "The metric's name, printed under the figure."
        },
        {
          "name": "delta",
          "reflex": "delta",
          "type": "number",
          "optional": true,
          "doc": "Signed change, printed with its sign and a direction mark."
        },
        {
          "name": "deltaTone",
          "reflex": "delta_tone",
          "type": "'up' | 'down' | 'flat'",
          "optional": true,
          "default": "delta",
          "doc": "Direction of the mark; from the sign of `delta` by default."
        }
      ],
      "demo": "KPI_CARD_DEMO",
      "demoSample": [
        {
          "value": 118
        },
        {
          "value": 124
        },
        {
          "value": 121
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "bar-chart",
      "names": {
        "react": "BarChart",
        "vue": "SpBarChart",
        "angular": "sp-bar-chart",
        "reflex": "bar_chart"
      },
      "imports": {
        "react": "@silverpoint/react/bar-chart",
        "vue": "@silverpoint/vue/bar-chart",
        "angular": "@silverpoint/angular/bar-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "bars",
      "summary": "Pill bars, as columns or rows, with an optional second series.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          },
          {
            "role": "secondary",
            "prop": "secondaryKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "compare",
        "rank"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "secondaryKey",
          "reflex": "secondary_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "'columns' | 'rows'",
          "optional": true,
          "doc": ""
        }
      ],
      "demo": "BAR_CHART_DEMO",
      "demoKeys": {
        "xKey": "x",
        "valueKey": "value",
        "secondaryKey": "previous"
      },
      "demoSample": [
        {
          "x": "Q1",
          "value": 42,
          "previous": 35
        },
        {
          "x": "Q2",
          "value": 58,
          "previous": 44
        },
        {
          "x": "Q3",
          "value": 51,
          "previous": 49
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "stacked-bar-chart",
      "names": {
        "react": "StackedBarChart",
        "vue": "SpStackedBarChart",
        "angular": "sp-stacked-bar-chart",
        "reflex": "stacked_bar_chart"
      },
      "imports": {
        "react": "@silverpoint/react/stacked-bar-chart",
        "vue": "@silverpoint/vue/stacked-bar-chart",
        "angular": "@silverpoint/angular/stacked-bar-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "bars",
      "summary": "One stacked segment per key.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "values",
            "prop": "keys",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "compare",
        "part-to-whole"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "keys",
          "reflex": "keys",
          "type": "readonly string[]",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "names",
          "reflex": "names",
          "type": "readonly string[]",
          "optional": true,
          "doc": "Display names of the keys, in order; the keys themselves by default. Ignored without `data`."
        }
      ],
      "demo": "STACKED_BAR_CHART_DEMO",
      "demoKeys": {
        "0": "free",
        "1": "pro",
        "2": "team"
      },
      "demoSample": [
        {
          "x": "Jan",
          "free": 40,
          "pro": 18,
          "team": 6
        },
        {
          "x": "Feb",
          "free": 46,
          "pro": 21,
          "team": 9
        },
        {
          "x": "Mar",
          "free": 38,
          "pro": 26,
          "team": 11
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "composed-chart",
      "names": {
        "react": "ComposedChart",
        "vue": "SpComposedChart",
        "angular": "sp-composed-chart",
        "reflex": "composed_chart"
      },
      "imports": {
        "react": "@silverpoint/react/composed-chart",
        "vue": "@silverpoint/vue/composed-chart",
        "angular": "@silverpoint/angular/composed-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "bars",
      "summary": "Columns and a spline on one value scale.",
      "data": {
        "shape": "series",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "bar",
            "prop": "barKey",
            "type": "number",
            "required": true
          },
          {
            "role": "line",
            "prop": "lineKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "compare",
        "trend"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "barKey",
          "reflex": "bar_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'bar'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "lineKey",
          "reflex": "line_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'line'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "showLine",
          "reflex": "show_line",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": ""
        }
      ],
      "demo": "COMPOSED_CHART_DEMO",
      "demoKeys": {
        "xKey": "x",
        "barKey": "revenue",
        "lineKey": "margin"
      },
      "demoSample": [
        {
          "x": "Jan",
          "revenue": 42,
          "margin": 18
        },
        {
          "x": "Feb",
          "revenue": 48,
          "margin": 21
        },
        {
          "x": "Mar",
          "revenue": 39,
          "margin": 17
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "waterfall-chart",
      "names": {
        "react": "WaterfallChart",
        "vue": "SpWaterfallChart",
        "angular": "sp-waterfall-chart",
        "reflex": "waterfall_chart"
      },
      "imports": {
        "react": "@silverpoint/react/waterfall-chart",
        "vue": "@silverpoint/vue/waterfall-chart",
        "angular": "@silverpoint/angular/waterfall-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "bars",
      "summary": "Totals from zero and floating deltas from the running total.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "step",
            "prop": "stepKey",
            "type": "string",
            "required": true
          },
          {
            "role": "base",
            "prop": "baseKey",
            "type": "number",
            "required": false
          },
          {
            "role": "delta",
            "prop": "deltaKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "change",
        "part-to-whole"
      ],
      "props": [
        {
          "name": "stepKey",
          "reflex": "step_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'step'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "baseKey",
          "reflex": "base_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'base'",
          "doc": "An absolute total: the bar starts at zero and resets the running total. Ignored without `data`."
        },
        {
          "name": "deltaKey",
          "reflex": "delta_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'delta'",
          "doc": "A change from the running total. Ignored without `data`."
        }
      ],
      "demo": "WATERFALL_CHART_DEMO",
      "demoSample": [
        {
          "step": "Opening",
          "base": 120
        },
        {
          "step": "Sales",
          "delta": 64
        },
        {
          "step": "Services",
          "delta": 22
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "funnel-chart",
      "names": {
        "react": "FunnelChart",
        "vue": "SpFunnelChart",
        "angular": "sp-funnel-chart",
        "reflex": "funnel_chart"
      },
      "imports": {
        "react": "@silverpoint/react/funnel-chart",
        "vue": "@silverpoint/vue/funnel-chart",
        "angular": "@silverpoint/angular/funnel-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "bars",
      "summary": "Horizontal, centred stages.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "stage",
            "prop": "stageKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "progress",
        "compare"
      ],
      "props": [
        {
          "name": "stageKey",
          "reflex": "stage_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'stage'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        }
      ],
      "demo": "FUNNEL_CHART_DEMO",
      "demoSample": [
        {
          "stage": "Visits",
          "value": 12400
        },
        {
          "stage": "Product",
          "value": 6800
        },
        {
          "stage": "Cart",
          "value": 2900
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "candlestick-chart",
      "names": {
        "react": "CandlestickChart",
        "vue": "SpCandlestickChart",
        "angular": "sp-candlestick-chart",
        "reflex": "candlestick_chart"
      },
      "imports": {
        "react": "@silverpoint/react/candlestick-chart",
        "vue": "@silverpoint/vue/candlestick-chart",
        "angular": "@silverpoint/angular/candlestick-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "bars",
      "summary": "OHLC bodies and wicks.",
      "data": {
        "shape": "intervals",
        "fields": [
          {
            "role": "time",
            "prop": "timeKey",
            "type": "string",
            "required": true
          },
          {
            "role": "open",
            "prop": "openKey",
            "type": "number",
            "required": true
          },
          {
            "role": "high",
            "prop": "highKey",
            "type": "number",
            "required": true
          },
          {
            "role": "low",
            "prop": "lowKey",
            "type": "number",
            "required": true
          },
          {
            "role": "close",
            "prop": "closeKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "change",
        "trend"
      ],
      "props": [
        {
          "name": "timeKey",
          "reflex": "time_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'time'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "openKey",
          "reflex": "open_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'open'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "highKey",
          "reflex": "high_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'high'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "lowKey",
          "reflex": "low_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'low'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "closeKey",
          "reflex": "close_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'close'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "bounds",
          "reflex": "bounds",
          "type": "readonly [number, number]",
          "optional": true,
          "doc": "Price bounds of the scale; derived from the data when omitted (REQ-097)."
        }
      ],
      "demo": "CANDLESTICK_CHART_DEMO",
      "demoSample": [
        {
          "time": "Mon",
          "open": 102,
          "high": 108,
          "low": 99,
          "close": 106
        },
        {
          "time": "Tue",
          "open": 106,
          "high": 109,
          "low": 101,
          "close": 103
        },
        {
          "time": "Wed",
          "open": 103,
          "high": 105,
          "low": 97,
          "close": 99
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "area-chart",
      "names": {
        "react": "AreaChart",
        "vue": "SpAreaChart",
        "angular": "sp-area-chart",
        "reflex": "area_chart"
      },
      "imports": {
        "react": "@silverpoint/react/area-chart",
        "vue": "@silverpoint/vue/area-chart",
        "angular": "@silverpoint/angular/area-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "areas",
      "summary": "A curved, toned area under its line.",
      "data": {
        "shape": "series",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "trend",
        "change"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "curve",
          "reflex": "curve",
          "type": "LineCurve",
          "optional": true,
          "default": "'monotone'",
          "doc": ""
        }
      ],
      "demo": "AREA_CHART_DEMO",
      "demoSample": [
        {
          "x": "Mon",
          "value": 32
        },
        {
          "x": "Tue",
          "value": 45
        },
        {
          "x": "Wed",
          "value": 41
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "range-band-chart",
      "names": {
        "react": "RangeBandChart",
        "vue": "SpRangeBandChart",
        "angular": "sp-range-band-chart",
        "reflex": "range_band_chart"
      },
      "imports": {
        "react": "@silverpoint/react/range-band-chart",
        "vue": "@silverpoint/vue/range-band-chart",
        "angular": "@silverpoint/angular/range-band-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "areas",
      "summary": "The band between a low and a high series.",
      "data": {
        "shape": "intervals",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "low",
            "prop": "lowKey",
            "type": "number",
            "required": true
          },
          {
            "role": "high",
            "prop": "highKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "uncertainty",
        "trend"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "lowKey",
          "reflex": "low_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'low'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "highKey",
          "reflex": "high_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'high'",
          "doc": "Ignored without `data`."
        }
      ],
      "demo": "RANGE_BAND_CHART_DEMO",
      "demoSample": [
        {
          "x": "Mon",
          "low": 11,
          "high": 19
        },
        {
          "x": "Tue",
          "low": 12,
          "high": 22
        },
        {
          "x": "Wed",
          "low": 14,
          "high": 24
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "stream-chart",
      "names": {
        "react": "StreamChart",
        "vue": "SpStreamChart",
        "angular": "sp-stream-chart",
        "reflex": "stream_chart"
      },
      "imports": {
        "react": "@silverpoint/react/stream-chart",
        "vue": "@silverpoint/vue/stream-chart",
        "angular": "@silverpoint/angular/stream-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "areas",
      "summary": "Two waves, overlaid or stacked.",
      "data": {
        "shape": "series",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "values",
            "prop": "keys",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "trend",
        "part-to-whole",
        "compare"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "keys",
          "reflex": "keys",
          "type": "readonly string[]",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "stacked",
          "reflex": "stacked",
          "type": "boolean",
          "optional": true,
          "default": "false",
          "doc": ""
        }
      ],
      "demo": "STREAM_CHART_DEMO",
      "demoKeys": {
        "0": "organic",
        "1": "paid"
      },
      "demoSample": [
        {
          "x": "Mon",
          "organic": 22,
          "paid": 14
        },
        {
          "x": "Tue",
          "organic": 28,
          "paid": 18
        },
        {
          "x": "Wed",
          "organic": 35,
          "paid": 16
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "scatter-chart",
      "names": {
        "react": "ScatterChart",
        "vue": "SpScatterChart",
        "angular": "sp-scatter-chart",
        "reflex": "scatter_chart"
      },
      "imports": {
        "react": "@silverpoint/react/scatter-chart",
        "vue": "@silverpoint/vue/scatter-chart",
        "angular": "@silverpoint/angular/scatter-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "points-grids",
      "summary": "Points on two linear scales, optionally sized.",
      "data": {
        "shape": "points",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "number",
            "required": true
          },
          {
            "role": "y",
            "prop": "yKey",
            "type": "number",
            "required": true
          },
          {
            "role": "size",
            "prop": "sizeKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "correlation",
        "distribution"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "yKey",
          "reflex": "y_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "sizeKey",
          "reflex": "size_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "sizeRange",
          "reflex": "size_range",
          "type": "readonly [number, number]",
          "optional": true,
          "default": "[60, 240]",
          "doc": "Marker area in px², smallest to largest; `[60, 240]` by default."
        }
      ],
      "demo": "SCATTER_CHART_DEMO",
      "demoSample": [
        {
          "x": 152,
          "y": 51,
          "size": 2
        },
        {
          "x": 158,
          "y": 56,
          "size": 4
        },
        {
          "x": 161,
          "y": 54,
          "size": 3
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "bubble-chart",
      "names": {
        "react": "BubbleChart",
        "vue": "SpBubbleChart",
        "angular": "sp-bubble-chart",
        "reflex": "bubble_chart"
      },
      "imports": {
        "react": "@silverpoint/react/bubble-chart",
        "vue": "@silverpoint/vue/bubble-chart",
        "angular": "@silverpoint/angular/bubble-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "points-grids",
      "summary": "Circles whose area encodes `sizeKey`.",
      "data": {
        "shape": "points",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "number",
            "required": true
          },
          {
            "role": "y",
            "prop": "yKey",
            "type": "number",
            "required": true
          },
          {
            "role": "size",
            "prop": "sizeKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "correlation",
        "compare"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "yKey",
          "reflex": "y_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "sizeKey",
          "reflex": "size_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "sizeRange",
          "reflex": "size_range",
          "type": "readonly [number, number]",
          "optional": true,
          "default": "[100, 500]",
          "doc": "Circle area in px², smallest to largest; `[100, 500]` by default."
        }
      ],
      "demo": "BUBBLE_CHART_DEMO",
      "demoSample": [
        {
          "x": 2,
          "y": 18,
          "size": 40
        },
        {
          "x": 5,
          "y": 24,
          "size": 120
        },
        {
          "x": 8,
          "y": 12,
          "size": 65
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "donut-chart",
      "names": {
        "react": "DonutChart",
        "vue": "SpDonutChart",
        "angular": "sp-donut-chart",
        "reflex": "donut_chart"
      },
      "imports": {
        "react": "@silverpoint/react/donut-chart",
        "vue": "@silverpoint/vue/donut-chart",
        "angular": "@silverpoint/angular/donut-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "Sectors ∝ value around a central readout.",
      "data": {
        "shape": "parts",
        "fields": [
          {
            "role": "name",
            "prop": "nameKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "part-to-whole"
      ],
      "props": [
        {
          "name": "nameKey",
          "reflex": "name_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'name'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "centerValue",
          "reflex": "center_value",
          "type": "string | number",
          "optional": true,
          "doc": "Printed in the centre; the total by default."
        },
        {
          "name": "centerLabel",
          "reflex": "center_label",
          "type": "string",
          "optional": true,
          "doc": "A line under the centre value."
        },
        {
          "name": "legend",
          "reflex": "legend",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Names every sector with its share beside the ring; `true` by default."
        }
      ],
      "demo": "DONUT_CHART_DEMO",
      "demoSample": [
        {
          "name": "Rent",
          "value": 38
        },
        {
          "name": "Food",
          "value": 22
        },
        {
          "name": "Savings",
          "value": 15
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "radar-chart",
      "names": {
        "react": "RadarChart",
        "vue": "SpRadarChart",
        "angular": "sp-radar-chart",
        "reflex": "radar_chart"
      },
      "imports": {
        "react": "@silverpoint/react/radar-chart",
        "vue": "@silverpoint/vue/radar-chart",
        "angular": "@silverpoint/angular/radar-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "One spoke per subject, a closed polygon of values.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "subject",
            "prop": "subjectKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "compare"
      ],
      "props": [
        {
          "name": "subjectKey",
          "reflex": "subject_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'subject'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "domain",
          "reflex": "domain",
          "type": "readonly [number, number]",
          "optional": true,
          "doc": "The value range along a spoke; `[0, the largest value]`, niced, by default."
        }
      ],
      "demo": "RADAR_CHART_DEMO",
      "demoSample": [
        {
          "subject": "Speed",
          "value": 8
        },
        {
          "subject": "Range",
          "value": 6
        },
        {
          "subject": "Comfort",
          "value": 7
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "polar-bar-chart",
      "names": {
        "react": "PolarBarChart",
        "vue": "SpPolarBarChart",
        "angular": "sp-polar-bar-chart",
        "reflex": "polar_bar_chart"
      },
      "imports": {
        "react": "@silverpoint/react/polar-bar-chart",
        "vue": "@silverpoint/vue/polar-bar-chart",
        "angular": "@silverpoint/angular/polar-bar-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "360° bars out from a hole, length ∝ value.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "name",
            "prop": "nameKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "compare",
        "rank"
      ],
      "props": [
        {
          "name": "nameKey",
          "reflex": "name_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'name'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        }
      ],
      "demo": "POLAR_BAR_CHART_DEMO",
      "demoSample": [
        {
          "name": "Jan",
          "value": 32
        },
        {
          "name": "Feb",
          "value": 28
        },
        {
          "name": "Mar",
          "value": 41
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "radial-arc-group",
      "names": {
        "react": "RadialArcGroup",
        "vue": "SpRadialArcGroup",
        "angular": "sp-radial-arc-group",
        "reflex": "radial_arc_group"
      },
      "imports": {
        "react": "@silverpoint/react/radial-arc-group",
        "vue": "@silverpoint/vue/radial-arc-group",
        "angular": "@silverpoint/angular/radial-arc-group",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "Concentric 180° tracks, sweep ∝ value / the largest.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "name",
            "prop": "nameKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "compare",
        "progress"
      ],
      "props": [
        {
          "name": "nameKey",
          "reflex": "name_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        }
      ],
      "demo": "RADIAL_ARC_GROUP_DEMO",
      "demoSample": [
        {
          "name": "Direct",
          "value": 84
        },
        {
          "name": "Partners",
          "value": 62
        },
        {
          "name": "Online",
          "value": 47
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "radial-rings",
      "names": {
        "react": "RadialRings",
        "vue": "SpRadialRings",
        "angular": "sp-radial-rings",
        "reflex": "radial_rings"
      },
      "imports": {
        "react": "@silverpoint/react/radial-rings",
        "vue": "@silverpoint/vue/radial-rings",
        "angular": "@silverpoint/angular/radial-rings",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "Concentric progress rings, sweep ∝ value in 0-100.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "name",
            "prop": "nameKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "progress"
      ],
      "props": [
        {
          "name": "nameKey",
          "reflex": "name_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        }
      ],
      "demo": "RADIAL_RINGS_DEMO",
      "demoSample": [
        {
          "name": "Move",
          "value": 82
        },
        {
          "name": "Exercise",
          "value": 64
        },
        {
          "name": "Stand",
          "value": 100
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "gauge-arc",
      "names": {
        "react": "GaugeArc",
        "vue": "SpGaugeArc",
        "angular": "sp-gauge-arc",
        "reflex": "gauge_arc"
      },
      "imports": {
        "react": "@silverpoint/react/gauge-arc",
        "vue": "@silverpoint/vue/gauge-arc",
        "angular": "@silverpoint/angular/gauge-arc",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "A 240° arc swept to a percent.",
      "data": {
        "shape": "single",
        "fields": []
      },
      "intents": [
        "kpi",
        "progress"
      ],
      "props": [
        {
          "name": "percent",
          "reflex": "percent",
          "type": "number",
          "optional": true,
          "doc": "0 to 100; saturated at the ends outside it."
        },
        {
          "name": "caption",
          "reflex": "caption",
          "type": "string",
          "optional": true,
          "doc": "Names the measure under the readout."
        },
        {
          "name": "readout",
          "reflex": "readout",
          "type": "string",
          "optional": true,
          "doc": "Printed in place of the percent."
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "meter-chart",
      "names": {
        "react": "MeterChart",
        "vue": "SpMeterChart",
        "angular": "sp-meter-chart",
        "reflex": "meter_chart"
      },
      "imports": {
        "react": "@silverpoint/react/meter-chart",
        "vue": "@silverpoint/vue/meter-chart",
        "angular": "@silverpoint/angular/meter-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "A semicircular meter with a needle at a percent.",
      "data": {
        "shape": "single",
        "fields": []
      },
      "intents": [
        "kpi",
        "progress"
      ],
      "props": [
        {
          "name": "percent",
          "reflex": "percent",
          "type": "number",
          "optional": true,
          "doc": "0 to 100; saturated at the ends outside it."
        },
        {
          "name": "caption",
          "reflex": "caption",
          "type": "string",
          "optional": true,
          "doc": "Names the measure under the readout."
        },
        {
          "name": "readout",
          "reflex": "readout",
          "type": "string",
          "optional": true,
          "doc": "Printed in place of the percent."
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "coxcomb-chart",
      "names": {
        "react": "CoxcombChart",
        "vue": "SpCoxcombChart",
        "angular": "sp-coxcomb-chart",
        "reflex": "coxcomb_chart"
      },
      "imports": {
        "react": "@silverpoint/react/coxcomb-chart",
        "vue": "@silverpoint/vue/coxcomb-chart",
        "angular": "@silverpoint/angular/coxcomb-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "Equal angles, sector area ∝ value.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "name",
            "prop": "nameKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "compare",
        "part-to-whole"
      ],
      "props": [
        {
          "name": "nameKey",
          "reflex": "name_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'name'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "startAngle",
          "reflex": "start_angle",
          "type": "number",
          "optional": true,
          "default": "0",
          "doc": "Where the first sector starts, in degrees clockwise from 12 o'clock; 0 by default."
        }
      ],
      "demo": "COXCOMB_CHART_DEMO",
      "demoSample": [
        {
          "name": "Mon",
          "value": 42
        },
        {
          "name": "Tue",
          "value": 35
        },
        {
          "name": "Wed",
          "value": 31
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "wind-rose",
      "names": {
        "react": "WindRose",
        "vue": "SpWindRose",
        "angular": "sp-wind-rose",
        "reflex": "wind_rose"
      },
      "imports": {
        "react": "@silverpoint/react/wind-rose",
        "vue": "@silverpoint/vue/wind-rose",
        "angular": "@silverpoint/angular/wind-rose",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "Observations of (bearing, speed) binned by compass sector and speed.",
      "data": {
        "shape": "distribution",
        "fields": [
          {
            "role": "bearing",
            "prop": "bearingKey",
            "type": "number",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "distribution"
      ],
      "props": [
        {
          "name": "bearingKey",
          "reflex": "bearing_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'bearing'",
          "doc": "Where the wind blows from, in degrees clockwise from north. Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'speed'",
          "doc": "The wind speed; 0 is a calm, which has no direction. Ignored without `data`."
        },
        {
          "name": "sectors",
          "reflex": "sectors",
          "type": "number",
          "optional": true,
          "default": "16",
          "doc": "Compass sectors: 4, 8, 16 or 32; 16 by default."
        },
        {
          "name": "bins",
          "reflex": "bins",
          "type": "readonly number[]",
          "optional": true,
          "default": "[5, 10, 15, 20]",
          "doc": "Ascending speed thresholds that split each sector; `[5, 10, 15, 20]` by default."
        }
      ],
      "demo": "WIND_ROSE_DEMO",
      "demoSample": [
        {
          "bearing": 180,
          "speed": 11
        },
        {
          "bearing": 170,
          "speed": 11
        },
        {
          "bearing": 180,
          "speed": 9
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "volvelle-chart",
      "names": {
        "react": "VolvelleChart",
        "vue": "SpVolvelleChart",
        "angular": "sp-volvelle-chart",
        "reflex": "volvelle_chart"
      },
      "imports": {
        "react": "@silverpoint/react/volvelle-chart",
        "vue": "@silverpoint/vue/volvelle-chart",
        "angular": "@silverpoint/angular/volvelle-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "Concentric categorical rings read against one index.",
      "data": {
        "shape": "categories",
        "fields": []
      },
      "intents": [
        "schedule",
        "compare"
      ],
      "props": [
        {
          "name": "rings",
          "reflex": "rings",
          "type": "number",
          "optional": true,
          "doc": "Rings shown, from the inside out; all by default."
        },
        {
          "name": "indexRing",
          "reflex": "index_ring",
          "type": "number",
          "optional": true,
          "default": "0",
          "doc": "The ring whose segment is brought under the index, 0-based; 0 by default. Without `data`, it addresses the demo’s rings: `Day`, `Shift`, `Team`."
        },
        {
          "name": "indexValue",
          "reflex": "index_value",
          "type": "string",
          "optional": true,
          "doc": "The segment of `indexRing` under the index; its first segment by default. Without `data`, it addresses the demo’s rings: `Day`, `Shift`, `Team`."
        }
      ],
      "demo": "VOLVELLE_CHART_DEMO",
      "demoSample": [
        {
          "label": "Day",
          "segments": [
            "Mon",
            "Tue",
            "Wed",
            "Thu",
            "Fri",
            "Sat",
            "Sun"
          ]
        },
        {
          "label": "Shift",
          "segments": [
            "Early",
            "Late",
            "Night"
          ]
        },
        {
          "label": "Team",
          "segments": [
            "Atlas",
            "Borealis",
            "Cygnus",
            "Draco",
            "Eridanus"
          ]
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "chord-ring",
      "names": {
        "react": "ChordRing",
        "vue": "SpChordRing",
        "angular": "sp-chord-ring",
        "reflex": "chord_ring"
      },
      "imports": {
        "react": "@silverpoint/react/chord-ring",
        "vue": "@silverpoint/vue/chord-ring",
        "angular": "@silverpoint/angular/chord-ring",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "flows",
      "summary": "Directed flows between categories around a circle.",
      "data": {
        "shape": "links",
        "fields": [
          {
            "role": "source",
            "prop": "sourceKey",
            "type": "string",
            "required": true
          },
          {
            "role": "target",
            "prop": "targetKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "flow",
        "network"
      ],
      "props": [
        {
          "name": "sourceKey",
          "reflex": "source_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'source'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "targetKey",
          "reflex": "target_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'target'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "maxCategories",
          "reflex": "max_categories",
          "type": "number",
          "optional": true,
          "default": "12",
          "doc": "Categories drawn; past it the smallest merge into \"Other\" (`SP010`). 12 by default."
        }
      ],
      "demo": "CHORD_RING_DEMO",
      "demoSample": [
        {
          "source": "Home",
          "target": "Shop",
          "value": 42
        },
        {
          "source": "Home",
          "target": "Blog",
          "value": 28
        },
        {
          "source": "Blog",
          "target": "Shop",
          "value": 16
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "orbit-chart",
      "names": {
        "react": "OrbitChart",
        "vue": "SpOrbitChart",
        "angular": "sp-orbit-chart",
        "reflex": "orbit_chart"
      },
      "imports": {
        "react": "@silverpoint/react/orbit-chart",
        "vue": "@silverpoint/vue/orbit-chart",
        "angular": "@silverpoint/angular/orbit-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "radial",
      "summary": "Nested elliptical orbits with markers along them.",
      "data": {
        "shape": "events",
        "fields": [
          {
            "role": "markers",
            "prop": "markerKey",
            "type": "array",
            "required": true
          },
          {
            "role": "period",
            "prop": "periodKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "schedule"
      ],
      "props": [
        {
          "name": "orbits",
          "reflex": "orbits",
          "type": "number",
          "optional": true,
          "doc": "Orbits shown, from the inside out; all by default."
        },
        {
          "name": "markerKey",
          "reflex": "marker_key",
          "type": "Accessor<readonly unknown[] | null | undefined>",
          "optional": true,
          "default": "'markers'",
          "doc": "A row's markers; `'markers'` by default. Ignored without `data`."
        },
        {
          "name": "periodKey",
          "reflex": "period_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'period'",
          "doc": "A marker's period, 0-1 over the cycle; `'period'` by default. Ignored without `data`."
        }
      ],
      "demo": "ORBIT_CHART_DEMO",
      "demoSample": [
        {
          "label": "2023",
          "markers": [
            {
              "period": 0.08,
              "value": 12
            },
            {
              "period": 0.33,
              "value": 30
            },
            {
              "period": 0.61,
              "value": 18
            },
            {
              "period": 0.9,
              "value": 24
            }
          ]
        },
        {
          "label": "2024",
          "markers": [
            {
              "period": 0.12,
              "value": 20
            },
            {
              "period": 0.4,
              "value": 42
            },
            {
              "period": 0.66,
              "value": 15
            },
            {
              "period": 0.87,
              "value": 33
            }
          ]
        },
        {
          "label": "2025",
          "markers": [
            {
              "period": 0.05,
              "value": 26
            },
            {
              "period": 0.29,
              "value": 38
            },
            {
              "period": 0.55,
              "value": 50
            },
            {
              "period": 0.81,
              "value": 21
            }
          ]
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "histogram-chart",
      "names": {
        "react": "HistogramChart",
        "vue": "SpHistogramChart",
        "angular": "sp-histogram-chart",
        "reflex": "histogram_chart"
      },
      "imports": {
        "react": "@silverpoint/react/histogram-chart",
        "vue": "@silverpoint/vue/histogram-chart",
        "angular": "@silverpoint/angular/histogram-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "Raw observations binned in the core.",
      "data": {
        "shape": "distribution",
        "fields": [
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "distribution"
      ],
      "props": [
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "bins",
          "reflex": "bins",
          "type": "number | readonly number[]",
          "optional": true,
          "doc": "A number asks for that many equal-width bins over the niced extent; an array gives the thresholds, increasing. Freedman–Diaconis by default, Sturges when the IQR is 0 (REQ-432)."
        },
        {
          "name": "cumulative",
          "reflex": "cumulative",
          "type": "boolean",
          "optional": true,
          "doc": "Turns the counts into a running total."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "ChartOrientation",
          "optional": true,
          "doc": ""
        }
      ],
      "demo": "HISTOGRAM_CHART_DEMO",
      "demoKeys": {
        "valueKey": "minutes"
      },
      "demoSample": [
        {
          "reader": "R001",
          "device": "desktop",
          "minutes": 4
        },
        {
          "reader": "R002",
          "device": "phone",
          "minutes": 17
        },
        {
          "reader": "R003",
          "device": "phone",
          "minutes": 3
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "ecdf-chart",
      "names": {
        "react": "EcdfChart",
        "vue": "SpEcdfChart",
        "angular": "sp-ecdf-chart",
        "reflex": "ecdf_chart"
      },
      "imports": {
        "react": "@silverpoint/react/ecdf-chart",
        "vue": "@silverpoint/vue/ecdf-chart",
        "angular": "@silverpoint/angular/ecdf-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "The empirical cumulative distribution as a step function.",
      "data": {
        "shape": "distribution",
        "fields": [
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          },
          {
            "role": "group",
            "prop": "groupKey",
            "type": "string",
            "required": false
          }
        ]
      },
      "intents": [
        "distribution",
        "compare"
      ],
      "props": [
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "groupKey",
          "reflex": "group_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Two groups at most are drawn. Ignored without `data`."
        },
        {
          "name": "markers",
          "reflex": "markers",
          "type": "readonly number[]",
          "optional": true,
          "doc": "Quantiles, in 0-1, drawn as rules."
        }
      ],
      "demo": "ECDF_CHART_DEMO",
      "demoKeys": {
        "valueKey": "minutes",
        "groupKey": "device"
      },
      "demoSample": [
        {
          "reader": "R001",
          "device": "desktop",
          "minutes": 4
        },
        {
          "reader": "R002",
          "device": "phone",
          "minutes": 17
        },
        {
          "reader": "R003",
          "device": "phone",
          "minutes": 3
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "box-plot-chart",
      "names": {
        "react": "BoxPlotChart",
        "vue": "SpBoxPlotChart",
        "angular": "sp-box-plot-chart",
        "reflex": "box_plot_chart"
      },
      "imports": {
        "react": "@silverpoint/react/box-plot-chart",
        "vue": "@silverpoint/vue/box-plot-chart",
        "angular": "@silverpoint/angular/box-plot-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "Quartiles, median, Tukey whiskers and outliers per group.",
      "data": {
        "shape": "distribution",
        "fields": [
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          },
          {
            "role": "group",
            "prop": "groupKey",
            "type": "string",
            "required": false
          }
        ]
      },
      "intents": [
        "distribution",
        "compare"
      ],
      "props": [
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "groupKey",
          "reflex": "group_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "whisker",
          "reflex": "whisker",
          "type": "number",
          "optional": true,
          "default": "1.5",
          "doc": "Whisker reach as a multiple of the IQR; 1.5 by default (REQ-432)."
        },
        {
          "name": "outliers",
          "reflex": "outliers",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Draws the observations past the whiskers; `true` by default."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "ChartOrientation",
          "optional": true,
          "doc": ""
        }
      ],
      "demo": "BOX_PLOT_CHART_DEMO",
      "demoKeys": {
        "valueKey": "ms",
        "groupKey": "service"
      },
      "demoSample": [
        {
          "service": "Search",
          "ms": 220
        },
        {
          "service": "Search",
          "ms": 177
        },
        {
          "service": "Search",
          "ms": 158
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "violin-chart",
      "names": {
        "react": "ViolinChart",
        "vue": "SpViolinChart",
        "angular": "sp-violin-chart",
        "reflex": "violin_chart"
      },
      "imports": {
        "react": "@silverpoint/react/violin-chart",
        "vue": "@silverpoint/vue/violin-chart",
        "angular": "@silverpoint/angular/violin-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "A mirrored kernel density per group.",
      "data": {
        "shape": "distribution",
        "fields": [
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          },
          {
            "role": "group",
            "prop": "groupKey",
            "type": "string",
            "required": false
          }
        ]
      },
      "intents": [
        "distribution",
        "compare"
      ],
      "props": [
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "groupKey",
          "reflex": "group_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "bandwidth",
          "reflex": "bandwidth",
          "type": "number",
          "optional": true,
          "doc": "Kernel bandwidth in data units, shared by every group; Silverman's rule by default."
        },
        {
          "name": "quartiles",
          "reflex": "quartiles",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Marks the quartiles inside each violin; `true` by default."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "ChartOrientation",
          "optional": true,
          "doc": ""
        }
      ],
      "demo": "VIOLIN_CHART_DEMO",
      "demoKeys": {
        "valueKey": "ms",
        "groupKey": "service"
      },
      "demoSample": [
        {
          "service": "Search",
          "ms": 220
        },
        {
          "service": "Search",
          "ms": 177
        },
        {
          "service": "Search",
          "ms": 158
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "ridgeline-chart",
      "names": {
        "react": "RidgelineChart",
        "vue": "SpRidgelineChart",
        "angular": "sp-ridgeline-chart",
        "reflex": "ridgeline_chart"
      },
      "imports": {
        "react": "@silverpoint/react/ridgeline-chart",
        "vue": "@silverpoint/vue/ridgeline-chart",
        "angular": "@silverpoint/angular/ridgeline-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "A kernel density per group on overlapping baselines.",
      "data": {
        "shape": "distribution",
        "fields": [
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          },
          {
            "role": "group",
            "prop": "groupKey",
            "type": "string",
            "required": true
          }
        ]
      },
      "intents": [
        "distribution",
        "compare",
        "change"
      ],
      "props": [
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "groupKey",
          "reflex": "group_key",
          "type": "Accessor<string | null | undefined>",
          "optional": false,
          "doc": "The group of an observation; one ridge per group. Ignored without `data`."
        },
        {
          "name": "bandwidth",
          "reflex": "bandwidth",
          "type": "number",
          "optional": true,
          "doc": "Kernel bandwidth in data units, shared by every group; Silverman's rule by default."
        },
        {
          "name": "overlap",
          "reflex": "overlap",
          "type": "number",
          "optional": true,
          "default": "0.5",
          "doc": "How far a ridge reaches into the one behind it, 0-1; 0.5 by default."
        }
      ],
      "demo": "RIDGELINE_CHART_DEMO",
      "demoKeys": {
        "valueKey": "ms",
        "groupKey": "service"
      },
      "demoSample": [
        {
          "service": "Search",
          "ms": 220
        },
        {
          "service": "Search",
          "ms": 177
        },
        {
          "service": "Search",
          "ms": 158
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "beeswarm-chart",
      "names": {
        "react": "BeeswarmChart",
        "vue": "SpBeeswarmChart",
        "angular": "sp-beeswarm-chart",
        "reflex": "beeswarm_chart"
      },
      "imports": {
        "react": "@silverpoint/react/beeswarm-chart",
        "vue": "@silverpoint/vue/beeswarm-chart",
        "angular": "@silverpoint/angular/beeswarm-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "One point per observation, packed without overlap.",
      "data": {
        "shape": "distribution",
        "fields": [
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          },
          {
            "role": "group",
            "prop": "groupKey",
            "type": "string",
            "required": false
          },
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": false
          }
        ]
      },
      "intents": [
        "distribution"
      ],
      "props": [
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "groupKey",
          "reflex": "group_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Names the point in the readout and the table. Ignored without `data`."
        },
        {
          "name": "radius",
          "reflex": "radius",
          "type": "number",
          "optional": true,
          "default": "3",
          "doc": "Point radius in px; 3 by default."
        }
      ],
      "demo": "BEESWARM_CHART_DEMO",
      "demoKeys": {
        "valueKey": "minutes",
        "labelKey": "reader"
      },
      "demoSample": [
        {
          "reader": "R001",
          "device": "desktop",
          "minutes": 4
        },
        {
          "reader": "R002",
          "device": "phone",
          "minutes": 17
        },
        {
          "reader": "R003",
          "device": "phone",
          "minutes": 3
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "lollipop-chart",
      "names": {
        "react": "LollipopChart",
        "vue": "SpLollipopChart",
        "angular": "sp-lollipop-chart",
        "reflex": "lollipop_chart"
      },
      "imports": {
        "react": "@silverpoint/react/lollipop-chart",
        "vue": "@silverpoint/vue/lollipop-chart",
        "angular": "@silverpoint/angular/lollipop-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "A stem from the baseline and a head at the value.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "compare",
        "rank"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "ChartOrientation",
          "optional": true,
          "doc": ""
        },
        {
          "name": "sort",
          "reflex": "sort",
          "type": "'none' | 'ascending' | 'descending'",
          "optional": true,
          "doc": "Order of the categories; `none` keeps the data order."
        }
      ],
      "demo": "LOLLIPOP_CHART_DEMO",
      "demoKeys": {
        "xKey": "branch",
        "valueKey": "loans"
      },
      "demoSample": [
        {
          "branch": "Northgate",
          "loans": 2969
        },
        {
          "branch": "Riverside Commons",
          "loans": 2695
        },
        {
          "branch": "Old Mill",
          "loans": 6096
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "dumbbell-chart",
      "names": {
        "react": "DumbbellChart",
        "vue": "SpDumbbellChart",
        "angular": "sp-dumbbell-chart",
        "reflex": "dumbbell_chart"
      },
      "imports": {
        "react": "@silverpoint/react/dumbbell-chart",
        "vue": "@silverpoint/vue/dumbbell-chart",
        "angular": "@silverpoint/angular/dumbbell-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "Two values per category joined by a segment.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": true
          },
          {
            "role": "start",
            "prop": "startKey",
            "type": "number",
            "required": true
          },
          {
            "role": "end",
            "prop": "endKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "change",
        "compare"
      ],
      "props": [
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'label'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "startKey",
          "reflex": "start_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'start'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "endKey",
          "reflex": "end_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'end'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "names",
          "reflex": "names",
          "type": "readonly [string, string]",
          "optional": true,
          "default": "['start', 'end']",
          "doc": "Titles of the two values; `['start', 'end']` by default. Ignored without `data`."
        },
        {
          "name": "endMarker",
          "reflex": "end_marker",
          "type": "'dot' | 'arrow'",
          "optional": true,
          "doc": "`arrow` encodes the direction from the first value to the second."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "ChartOrientation",
          "optional": true,
          "default": "rows",
          "doc": "`rows` by default: long category names read across."
        }
      ],
      "demo": "DUMBBELL_CHART_DEMO",
      "demoKeys": {
        "labelKey": "clinic",
        "startKey": "y2024",
        "endKey": "y2025",
        "names": [
          "2024",
          "2025"
        ]
      },
      "demoSample": [
        {
          "clinic": "Ashford",
          "y2024": 59,
          "y2025": 66
        },
        {
          "clinic": "Brook Lane",
          "y2024": 24,
          "y2025": 30
        },
        {
          "clinic": "Castlegate",
          "y2024": 33,
          "y2025": 47
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "slope-chart",
      "names": {
        "react": "SlopeChart",
        "vue": "SpSlopeChart",
        "angular": "sp-slope-chart",
        "reflex": "slope_chart"
      },
      "imports": {
        "react": "@silverpoint/react/slope-chart",
        "vue": "@silverpoint/vue/slope-chart",
        "angular": "@silverpoint/angular/slope-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "Two period axes, one segment per category.",
      "data": {
        "shape": "categories",
        "fields": [
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": true
          },
          {
            "role": "start",
            "prop": "startKey",
            "type": "number",
            "required": true
          },
          {
            "role": "end",
            "prop": "endKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "change",
        "rank"
      ],
      "props": [
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'label'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "startKey",
          "reflex": "start_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'start'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "endKey",
          "reflex": "end_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'end'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "names",
          "reflex": "names",
          "type": "readonly [string, string]",
          "optional": true,
          "default": "['start', 'end']",
          "doc": "Titles of the two periods; `['start', 'end']` by default. Ignored without `data`."
        }
      ],
      "demo": "SLOPE_CHART_DEMO",
      "demoKeys": {
        "labelKey": "clinic",
        "startKey": "y2024",
        "endKey": "y2025",
        "names": [
          "2024",
          "2025"
        ]
      },
      "demoSample": [
        {
          "clinic": "Ashford",
          "y2024": 59,
          "y2025": 66
        },
        {
          "clinic": "Brook Lane",
          "y2024": 24,
          "y2025": 30
        },
        {
          "clinic": "Castlegate",
          "y2024": 33,
          "y2025": 47
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "bump-chart",
      "names": {
        "react": "BumpChart",
        "vue": "SpBumpChart",
        "angular": "sp-bump-chart",
        "reflex": "bump_chart"
      },
      "imports": {
        "react": "@silverpoint/react/bump-chart",
        "vue": "@silverpoint/vue/bump-chart",
        "angular": "@silverpoint/angular/bump-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "The rank of each series at each x.",
      "data": {
        "shape": "series",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "string",
            "required": true
          },
          {
            "role": "series",
            "prop": "seriesKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "rank",
        "change"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "seriesKey",
          "reflex": "series_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'series'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "order",
          "reflex": "order",
          "type": "'descending' | 'ascending'",
          "optional": true,
          "default": "'descending'",
          "doc": "`descending` gives rank 1 to the highest value (the default)."
        },
        {
          "name": "series",
          "reflex": "series",
          "type": "number",
          "optional": true,
          "doc": "Series drawn, the best-ranked first; all by default."
        }
      ],
      "demo": "BUMP_CHART_DEMO",
      "demoKeys": {
        "xKey": "season",
        "seriesKey": "team",
        "valueKey": "points"
      },
      "demoSample": [
        {
          "season": 2018,
          "team": "Kestrel",
          "points": 57
        },
        {
          "season": 2018,
          "team": "Otter",
          "points": 53
        },
        {
          "season": 2018,
          "team": "Lynx",
          "points": 52
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "error-bar-chart",
      "names": {
        "react": "ErrorBarChart",
        "vue": "SpErrorBarChart",
        "angular": "sp-error-bar-chart",
        "reflex": "error_bar_chart"
      },
      "imports": {
        "react": "@silverpoint/react/error-bar-chart",
        "vue": "@silverpoint/vue/error-bar-chart",
        "angular": "@silverpoint/angular/error-bar-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "A point estimate with its interval per category.",
      "data": {
        "shape": "intervals",
        "fields": [
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": true
          },
          {
            "role": "estimate",
            "prop": "estimateKey",
            "type": "number",
            "required": true
          },
          {
            "role": "low",
            "prop": "lowKey",
            "type": "number",
            "required": true
          },
          {
            "role": "high",
            "prop": "highKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "uncertainty",
        "compare"
      ],
      "props": [
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'label'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "estimateKey",
          "reflex": "estimate_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'estimate'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "lowKey",
          "reflex": "low_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'low'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "highKey",
          "reflex": "high_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'high'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "reference",
          "reflex": "reference",
          "type": "number",
          "optional": true,
          "doc": "A reference value drawn as a dotted rule."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "ChartOrientation",
          "optional": true,
          "default": "rows",
          "doc": "`rows` by default, as a forest plot reads."
        }
      ],
      "demo": "ERROR_BAR_CHART_DEMO",
      "demoKeys": {
        "labelKey": "arm",
        "estimateKey": "effect",
        "lowKey": "low",
        "highKey": "high"
      },
      "demoSample": [
        {
          "arm": "Arm A",
          "effect": 1.61,
          "low": 1.01,
          "high": 2.07
        },
        {
          "arm": "Arm B",
          "effect": 0.2,
          "low": -0.16,
          "high": 1.04
        },
        {
          "arm": "Arm C",
          "effect": 1.25,
          "low": 0.35,
          "high": 2.79
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "interval-chart",
      "names": {
        "react": "IntervalChart",
        "vue": "SpIntervalChart",
        "angular": "sp-interval-chart",
        "reflex": "interval_chart"
      },
      "imports": {
        "react": "@silverpoint/react/interval-chart",
        "vue": "@silverpoint/vue/interval-chart",
        "angular": "@silverpoint/angular/interval-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "Floating bars from start to end on lanes.",
      "data": {
        "shape": "intervals",
        "fields": [
          {
            "role": "lane",
            "prop": "laneKey",
            "type": "string",
            "required": true
          },
          {
            "role": "start",
            "prop": "startKey",
            "type": "number",
            "required": true
          },
          {
            "role": "end",
            "prop": "endKey",
            "type": "number",
            "required": true
          },
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": false
          }
        ]
      },
      "intents": [
        "schedule"
      ],
      "props": [
        {
          "name": "laneKey",
          "reflex": "lane_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'lane'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "startKey",
          "reflex": "start_key",
          "type": "Accessor<number | string | null | undefined>",
          "optional": true,
          "default": "'start'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "endKey",
          "reflex": "end_key",
          "type": "Accessor<number | string | null | undefined>",
          "optional": true,
          "default": "'end'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "axis",
          "reflex": "axis",
          "type": "'number' | 'date'",
          "optional": true,
          "default": "'number'",
          "doc": "`date` reads ISO `YYYY-MM-DD` days in UTC; `number` by default. Ignored without `data`."
        }
      ],
      "demo": "INTERVAL_CHART_DEMO",
      "demoKeys": {
        "laneKey": "crew",
        "startKey": "from",
        "endKey": "to",
        "labelKey": "task",
        "axis": "date"
      },
      "demoSample": [
        {
          "crew": "North crew",
          "task": "Signage",
          "from": "2026-03-15",
          "to": "2026-03-21"
        },
        {
          "crew": "North crew",
          "task": "Grading",
          "from": "2026-02-17",
          "to": "2026-03-07"
        },
        {
          "crew": "North crew",
          "task": "Signage",
          "from": "2026-03-09",
          "to": "2026-03-31"
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "diverging-bar-chart",
      "names": {
        "react": "DivergingBarChart",
        "vue": "SpDivergingBarChart",
        "angular": "sp-diverging-bar-chart",
        "reflex": "diverging_bar_chart"
      },
      "imports": {
        "react": "@silverpoint/react/diverging-bar-chart",
        "vue": "@silverpoint/vue/diverging-bar-chart",
        "angular": "@silverpoint/angular/diverging-bar-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "Ordered levels stacked on both sides of a neutral centre.",
      "data": {
        "shape": "parts",
        "fields": [
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": true
          },
          {
            "role": "levels",
            "prop": "levels",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "part-to-whole",
        "compare"
      ],
      "props": [
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'label'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "levels",
          "reflex": "levels",
          "type": "readonly string[]",
          "optional": false,
          "doc": "The level columns, most negative first. Ignored without `data`."
        },
        {
          "name": "neutral",
          "reflex": "neutral",
          "type": "number | null",
          "optional": true,
          "doc": "Index of the neutral level, split across the centre; `null` for none. The middle one by default."
        },
        {
          "name": "percent",
          "reflex": "percent",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Normalises each row to 100 %; `true` by default."
        }
      ],
      "demo": "DIVERGING_BAR_CHART_DEMO",
      "demoKeys": {
        "labelKey": "question",
        "levels": [
          "Strongly disagree",
          "Disagree",
          "Neutral",
          "Agree",
          "Strongly agree"
        ]
      },
      "demoSample": [
        {
          "question": "The site is easy to use",
          "Strongly disagree": 43,
          "Disagree": 53,
          "Neutral": 50,
          "Agree": 24,
          "Strongly agree": 29
        },
        {
          "question": "Prices are fair",
          "Strongly disagree": 38,
          "Disagree": 36,
          "Neutral": 62,
          "Agree": 42,
          "Strongly agree": 21
        },
        {
          "question": "Delivery was on time",
          "Strongly disagree": 40,
          "Disagree": 42,
          "Neutral": 45,
          "Agree": 31,
          "Strongly agree": 41
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "connected-scatter-chart",
      "names": {
        "react": "ConnectedScatterChart",
        "vue": "SpConnectedScatterChart",
        "angular": "sp-connected-scatter-chart",
        "reflex": "connected_scatter_chart"
      },
      "imports": {
        "react": "@silverpoint/react/connected-scatter-chart",
        "vue": "@silverpoint/vue/connected-scatter-chart",
        "angular": "@silverpoint/angular/connected-scatter-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "distributions-comparisons",
      "summary": "An ordered path through x-y points.",
      "data": {
        "shape": "points",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "number",
            "required": true
          },
          {
            "role": "y",
            "prop": "yKey",
            "type": "number",
            "required": true
          },
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": false
          }
        ]
      },
      "intents": [
        "correlation",
        "change"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "yKey",
          "reflex": "y_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'y'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "arrows",
          "reflex": "arrows",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Draws direction marks along the path; `true` by default."
        }
      ],
      "demo": "CONNECTED_SCATTER_CHART_DEMO",
      "demoKeys": {
        "xKey": "fare",
        "yKey": "riders",
        "labelKey": "year"
      },
      "demoSample": [
        {
          "year": 2012,
          "fare": 1.5,
          "riders": 39.8
        },
        {
          "year": 2013,
          "fare": 1.62,
          "riders": 41.8
        },
        {
          "year": 2014,
          "fare": 1.72,
          "riders": 42.7
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "waffle-chart",
      "names": {
        "react": "WaffleChart",
        "vue": "SpWaffleChart",
        "angular": "sp-waffle-chart",
        "reflex": "waffle_chart"
      },
      "imports": {
        "react": "@silverpoint/react/waffle-chart",
        "vue": "@silverpoint/vue/waffle-chart",
        "angular": "@silverpoint/angular/waffle-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "hierarchies-dimensions",
      "summary": "A unit grid filled in reading order by category.",
      "data": {
        "shape": "parts",
        "fields": [
          {
            "role": "name",
            "prop": "nameKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "part-to-whole",
        "progress"
      ],
      "props": [
        {
          "name": "nameKey",
          "reflex": "name_key",
          "type": "Accessor<string | number>",
          "optional": true,
          "default": "'name'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "cells",
          "reflex": "cells",
          "type": "number",
          "optional": true,
          "default": "100",
          "doc": "Cells in the grid; 100 by default."
        },
        {
          "name": "columns",
          "reflex": "columns",
          "type": "number",
          "optional": true,
          "default": "10",
          "doc": "Cells per row; 10 by default."
        }
      ],
      "demo": "WAFFLE_CHART_DEMO",
      "demoKeys": {
        "nameKey": "use",
        "valueKey": "kwh"
      },
      "demoSample": [
        {
          "use": "Heating",
          "kwh": 412
        },
        {
          "use": "Water heating",
          "kwh": 263
        },
        {
          "use": "Appliances",
          "kwh": 158
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "marimekko-chart",
      "names": {
        "react": "MarimekkoChart",
        "vue": "SpMarimekkoChart",
        "angular": "sp-marimekko-chart",
        "reflex": "marimekko_chart"
      },
      "imports": {
        "react": "@silverpoint/react/marimekko-chart",
        "vue": "@silverpoint/vue/marimekko-chart",
        "angular": "@silverpoint/angular/marimekko-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "hierarchies-dimensions",
      "summary": "Column width by total, segment height by share.",
      "data": {
        "shape": "matrix",
        "fields": [
          {
            "role": "column",
            "prop": "columnKey",
            "type": "string",
            "required": true
          },
          {
            "role": "segment",
            "prop": "segmentKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "part-to-whole",
        "compare"
      ],
      "props": [
        {
          "name": "columnKey",
          "reflex": "column_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'column'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "segmentKey",
          "reflex": "segment_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'segment'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Ignored without `data`."
        }
      ],
      "demo": "MARIMEKKO_CHART_DEMO",
      "demoKeys": {
        "columnKey": "region",
        "segmentKey": "channel",
        "valueKey": "sales"
      },
      "demoSample": [
        {
          "region": "North",
          "channel": "Retail",
          "sales": 115
        },
        {
          "region": "North",
          "channel": "Online",
          "sales": 80
        },
        {
          "region": "North",
          "channel": "Wholesale",
          "sales": 37
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "squarified-treemap",
      "names": {
        "react": "SquarifiedTreemap",
        "vue": "SpSquarifiedTreemap",
        "angular": "sp-squarified-treemap",
        "reflex": "squarified_treemap"
      },
      "imports": {
        "react": "@silverpoint/react/squarified-treemap",
        "vue": "@silverpoint/vue/squarified-treemap",
        "angular": "@silverpoint/angular/squarified-treemap",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "hierarchies-dimensions",
      "summary": "Nested rectangles, area by value, drillable through `rootId` and `onRootChange`.",
      "data": {
        "shape": "hierarchy",
        "fields": [
          {
            "role": "id",
            "prop": "idKey",
            "type": "string",
            "required": true
          },
          {
            "role": "parent",
            "prop": "parentKey",
            "type": "string",
            "required": true
          },
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": false
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "hierarchy",
        "part-to-whole"
      ],
      "props": [
        {
          "name": "idKey",
          "reflex": "id_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'id'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "parentKey",
          "reflex": "parent_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "default": "'parent'",
          "doc": "`null` for the root. Ignored without `data`."
        },
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Read on leaves; an internal node is the sum of its children. Ignored without `data`."
        },
        {
          "name": "depth",
          "reflex": "depth",
          "type": "number",
          "optional": true,
          "doc": "Levels drawn below the root; all by default."
        },
        {
          "name": "rootId",
          "reflex": "root_id",
          "type": "string | null",
          "optional": true,
          "doc": "The node drawn as root, controlled (REQ-439); the data root by default."
        }
      ],
      "demo": "SQUARIFIED_TREEMAP_DEMO",
      "demoKeys": {
        "idKey": "id",
        "parentKey": "parent",
        "labelKey": "name",
        "valueKey": "amount"
      },
      "demoSample": [
        {
          "id": "budget",
          "parent": null,
          "name": "City budget"
        },
        {
          "id": "works",
          "parent": "budget",
          "name": "Public works"
        },
        {
          "id": "works-01",
          "parent": "works",
          "name": "Roads"
        }
      ],
      "drillable": true,
      "stale": "0.7.0"
    },
    {
      "slug": "sunburst-chart",
      "names": {
        "react": "SunburstChart",
        "vue": "SpSunburstChart",
        "angular": "sp-sunburst-chart",
        "reflex": "sunburst_chart"
      },
      "imports": {
        "react": "@silverpoint/react/sunburst-chart",
        "vue": "@silverpoint/vue/sunburst-chart",
        "angular": "@silverpoint/angular/sunburst-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "hierarchies-dimensions",
      "summary": "A hierarchy as rings of arcs, drillable through `rootId` and `onRootChange`.",
      "data": {
        "shape": "hierarchy",
        "fields": [
          {
            "role": "id",
            "prop": "idKey",
            "type": "string",
            "required": true
          },
          {
            "role": "parent",
            "prop": "parentKey",
            "type": "string",
            "required": true
          },
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": false
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "hierarchy",
        "part-to-whole"
      ],
      "props": [
        {
          "name": "idKey",
          "reflex": "id_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'id'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "parentKey",
          "reflex": "parent_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "default": "'parent'",
          "doc": "`null` for the root. Ignored without `data`."
        },
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "Read on leaves; an internal node is the sum of its children. Ignored without `data`."
        },
        {
          "name": "depth",
          "reflex": "depth",
          "type": "number",
          "optional": true,
          "doc": "Rings drawn below the root; all by default."
        },
        {
          "name": "rootId",
          "reflex": "root_id",
          "type": "string | null",
          "optional": true,
          "doc": "The node drawn as root, controlled (REQ-439); the data root by default."
        }
      ],
      "demo": "SUNBURST_CHART_DEMO",
      "demoKeys": {
        "idKey": "id",
        "parentKey": "parent",
        "labelKey": "name",
        "valueKey": "amount"
      },
      "demoSample": [
        {
          "id": "budget",
          "parent": null,
          "name": "City budget"
        },
        {
          "id": "works",
          "parent": "budget",
          "name": "Public works"
        },
        {
          "id": "works-01",
          "parent": "works",
          "name": "Roads"
        }
      ],
      "drillable": true,
      "stale": "0.7.0"
    },
    {
      "slug": "tree-chart",
      "names": {
        "react": "TreeChart",
        "vue": "SpTreeChart",
        "angular": "sp-tree-chart",
        "reflex": "tree_chart"
      },
      "imports": {
        "react": "@silverpoint/react/tree-chart",
        "vue": "@silverpoint/vue/tree-chart",
        "angular": "@silverpoint/angular/tree-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "hierarchies-dimensions",
      "summary": "A tidy node-link tree.",
      "data": {
        "shape": "hierarchy",
        "fields": [
          {
            "role": "id",
            "prop": "idKey",
            "type": "string",
            "required": true
          },
          {
            "role": "parent",
            "prop": "parentKey",
            "type": "string",
            "required": true
          },
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": false
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "hierarchy"
      ],
      "props": [
        {
          "name": "idKey",
          "reflex": "id_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'id'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "parentKey",
          "reflex": "parent_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "default": "'parent'",
          "doc": "`null` for the root. Ignored without `data`."
        },
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "'horizontal' | 'vertical'",
          "optional": true,
          "doc": ""
        }
      ],
      "demo": "TREE_CHART_DEMO",
      "demoKeys": {
        "idKey": "id",
        "parentKey": "parent",
        "labelKey": "name",
        "valueKey": "amount"
      },
      "demoSample": [
        {
          "id": "budget",
          "parent": null,
          "name": "City budget"
        },
        {
          "id": "works",
          "parent": "budget",
          "name": "Public works"
        },
        {
          "id": "works-01",
          "parent": "works",
          "name": "Roads"
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "parallel-coordinates-chart",
      "names": {
        "react": "ParallelCoordinatesChart",
        "vue": "SpParallelCoordinatesChart",
        "angular": "sp-parallel-coordinates-chart",
        "reflex": "parallel_coordinates_chart"
      },
      "imports": {
        "react": "@silverpoint/react/parallel-coordinates-chart",
        "vue": "@silverpoint/vue/parallel-coordinates-chart",
        "angular": "@silverpoint/angular/parallel-coordinates-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "hierarchies-dimensions",
      "summary": "One polyline per row across parallel axes.",
      "data": {
        "shape": "matrix",
        "fields": [
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": false
          },
          {
            "role": "dimensions",
            "prop": "dimensions",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "correlation",
        "compare"
      ],
      "props": [
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "dimensions",
          "reflex": "dimensions",
          "type": "readonly string[]",
          "optional": false,
          "doc": "The dimension columns, in axis order. Ignored without `data`."
        },
        {
          "name": "domains",
          "reflex": "domains",
          "type": "Readonly<Record<string, readonly [number, number]>>",
          "optional": true,
          "doc": "Axis domains by dimension; derived from the data when omitted (REQ-097)."
        }
      ],
      "demo": "PARALLEL_COORDINATES_CHART_DEMO",
      "demoKeys": {
        "labelKey": "model",
        "dimensions": [
          "mass",
          "gears",
          "price",
          "range",
          "rating"
        ]
      },
      "demoSample": [
        {
          "model": "Model 01",
          "mass": 13.9,
          "gears": 15,
          "price": 3434,
          "range": 125,
          "rating": 1.5
        },
        {
          "model": "Model 02",
          "mass": 8.6,
          "gears": 22,
          "price": 3897,
          "range": 29,
          "rating": 3.8
        },
        {
          "model": "Model 03",
          "mass": 19.5,
          "gears": 13,
          "price": 3202,
          "range": 62,
          "rating": 2.9
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "polar-line-chart",
      "names": {
        "react": "PolarLineChart",
        "vue": "SpPolarLineChart",
        "angular": "sp-polar-line-chart",
        "reflex": "polar_line_chart"
      },
      "imports": {
        "react": "@silverpoint/react/polar-line-chart",
        "vue": "@silverpoint/vue/polar-line-chart",
        "angular": "@silverpoint/angular/polar-line-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "hierarchies-dimensions",
      "summary": "A line over angle and radius.",
      "data": {
        "shape": "series",
        "fields": [
          {
            "role": "angle",
            "prop": "angleKey",
            "type": "number",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "trend",
        "compare"
      ],
      "props": [
        {
          "name": "angleKey",
          "reflex": "angle_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'angle'",
          "doc": "In the units of `period`. Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "The radius, `≥ 0`. Ignored without `data`."
        },
        {
          "name": "period",
          "reflex": "period",
          "type": "number",
          "optional": true,
          "doc": "One turn, in the units of the angle; when set, the line closes. Ignored without `data`."
        },
        {
          "name": "startAngle",
          "reflex": "start_angle",
          "type": "number",
          "optional": true,
          "default": "0",
          "doc": "Where the angle 0 sits, in degrees clockwise from 12 o'clock; 0 by default."
        }
      ],
      "demo": "POLAR_LINE_CHART_DEMO",
      "demoKeys": {
        "angleKey": "month",
        "valueKey": "rain",
        "period": 12
      },
      "demoSample": [
        {
          "month": 0,
          "rain": 82
        },
        {
          "month": 1,
          "rain": 62
        },
        {
          "month": 2,
          "rain": 54
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "polar-scatter-chart",
      "names": {
        "react": "PolarScatterChart",
        "vue": "SpPolarScatterChart",
        "angular": "sp-polar-scatter-chart",
        "reflex": "polar_scatter_chart"
      },
      "imports": {
        "react": "@silverpoint/react/polar-scatter-chart",
        "vue": "@silverpoint/vue/polar-scatter-chart",
        "angular": "@silverpoint/angular/polar-scatter-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "hierarchies-dimensions",
      "summary": "Points over angle and radius.",
      "data": {
        "shape": "points",
        "fields": [
          {
            "role": "angle",
            "prop": "angleKey",
            "type": "number",
            "required": true
          },
          {
            "role": "radius",
            "prop": "radiusKey",
            "type": "number",
            "required": true
          },
          {
            "role": "size",
            "prop": "sizeKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "distribution",
        "correlation"
      ],
      "props": [
        {
          "name": "angleKey",
          "reflex": "angle_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'angle'",
          "doc": "In the units of `period`. Ignored without `data`."
        },
        {
          "name": "radiusKey",
          "reflex": "radius_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'radius'",
          "doc": "The radius, `≥ 0`. Ignored without `data`."
        },
        {
          "name": "sizeKey",
          "reflex": "size_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "period",
          "reflex": "period",
          "type": "number",
          "optional": true,
          "default": "360",
          "doc": "One turn, in the units of the angle; 360 by default. Ignored without `data`."
        }
      ],
      "demo": "POLAR_SCATTER_CHART_DEMO",
      "demoKeys": {
        "angleKey": "bearing",
        "radiusKey": "distance"
      },
      "demoSample": [
        {
          "bearing": 28,
          "distance": 2.5
        },
        {
          "bearing": 149.6,
          "distance": 1.4
        },
        {
          "bearing": 229.3,
          "distance": 19.6
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "density-bin-chart",
      "names": {
        "react": "DensityBinChart",
        "vue": "SpDensityBinChart",
        "angular": "sp-density-bin-chart",
        "reflex": "density_bin_chart"
      },
      "imports": {
        "react": "@silverpoint/react/density-bin-chart",
        "vue": "@silverpoint/vue/density-bin-chart",
        "angular": "@silverpoint/angular/density-bin-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "fields-networks",
      "summary": "X-y points counted in two-dimensional bins.",
      "data": {
        "shape": "points",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "number",
            "required": true
          },
          {
            "role": "y",
            "prop": "yKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "distribution",
        "correlation"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "yKey",
          "reflex": "y_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'y'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "binShape",
          "reflex": "bin_shape",
          "type": "'hexagon' | 'rect'",
          "optional": true,
          "doc": ""
        },
        {
          "name": "binSize",
          "reflex": "bin_size",
          "type": "number",
          "optional": true,
          "default": "14",
          "doc": "Bin size in px; 14 by default."
        }
      ],
      "demo": "DENSITY_BIN_CHART_DEMO",
      "demoKeys": {
        "xKey": "x",
        "yKey": "y"
      },
      "demoSample": [
        {
          "x": 18.48,
          "y": 44.44
        },
        {
          "x": 38.26,
          "y": 64.71
        },
        {
          "x": 39.92,
          "y": 61.68
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "contour-chart",
      "names": {
        "react": "ContourChart",
        "vue": "SpContourChart",
        "angular": "sp-contour-chart",
        "reflex": "contour_chart"
      },
      "imports": {
        "react": "@silverpoint/react/contour-chart",
        "vue": "@silverpoint/vue/contour-chart",
        "angular": "@silverpoint/angular/contour-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "fields-networks",
      "summary": "Iso-lines and filled bands of a density or a grid.",
      "data": {
        "shape": "points",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "number",
            "required": true
          },
          {
            "role": "y",
            "prop": "yKey",
            "type": "number",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "distribution",
        "correlation"
      ],
      "props": [
        {
          "name": "source",
          "reflex": "source",
          "type": "'points' | 'grid'",
          "optional": true,
          "doc": "`points` estimates a density from a point cloud; `grid` reads a regular grid of values."
        },
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "yKey",
          "reflex": "y_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'y'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'value'",
          "doc": "The grid value (`source: 'grid'`). Ignored without `data`."
        },
        {
          "name": "levels",
          "reflex": "levels",
          "type": "number | readonly number[]",
          "optional": true,
          "doc": "A count of levels, or the thresholds, increasing: in the grid's values, or as shares of the density's peak. Ignored without `data`."
        },
        {
          "name": "filled",
          "reflex": "filled",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Fills the bands between levels; `true` by default."
        }
      ],
      "demo": "CONTOUR_CHART_DEMO",
      "demoKeys": {
        "xKey": "x",
        "yKey": "y"
      },
      "demoSample": [
        {
          "x": 18.48,
          "y": 44.44
        },
        {
          "x": 38.26,
          "y": 64.71
        },
        {
          "x": 39.92,
          "y": 61.68
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "delaunay-chart",
      "names": {
        "react": "DelaunayChart",
        "vue": "SpDelaunayChart",
        "angular": "sp-delaunay-chart",
        "reflex": "delaunay_chart"
      },
      "imports": {
        "react": "@silverpoint/react/delaunay-chart",
        "vue": "@silverpoint/vue/delaunay-chart",
        "angular": "@silverpoint/angular/delaunay-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "fields-networks",
      "summary": "The triangulation of x-y points, or its Voronoi cells.",
      "data": {
        "shape": "points",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "number",
            "required": true
          },
          {
            "role": "y",
            "prop": "yKey",
            "type": "number",
            "required": true
          },
          {
            "role": "label",
            "prop": "labelKey",
            "type": "string",
            "required": false
          }
        ]
      },
      "intents": [
        "network",
        "distribution"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "yKey",
          "reflex": "y_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'y'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "labelKey",
          "reflex": "label_key",
          "type": "Accessor<string | null | undefined>",
          "optional": true,
          "doc": "Ignored without `data`."
        },
        {
          "name": "mesh",
          "reflex": "mesh",
          "type": "'delaunay' | 'voronoi'",
          "optional": true,
          "doc": ""
        }
      ],
      "demo": "DELAUNAY_CHART_DEMO",
      "demoKeys": {
        "xKey": "x",
        "yKey": "y",
        "labelKey": "label"
      },
      "demoSample": [
        {
          "label": "P01",
          "x": 45,
          "y": 27.3
        },
        {
          "label": "P02",
          "x": 37.4,
          "y": 55.6
        },
        {
          "label": "P03",
          "x": 90.6,
          "y": 39.1
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "vector-field-chart",
      "names": {
        "react": "VectorFieldChart",
        "vue": "SpVectorFieldChart",
        "angular": "sp-vector-field-chart",
        "reflex": "vector_field_chart"
      },
      "imports": {
        "react": "@silverpoint/react/vector-field-chart",
        "vue": "@silverpoint/vue/vector-field-chart",
        "angular": "@silverpoint/angular/vector-field-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "fields-networks",
      "summary": "An arrow per grid point.",
      "data": {
        "shape": "field",
        "fields": [
          {
            "role": "x",
            "prop": "xKey",
            "type": "number",
            "required": true
          },
          {
            "role": "y",
            "prop": "yKey",
            "type": "number",
            "required": true
          },
          {
            "role": "u",
            "prop": "uKey",
            "type": "number",
            "required": true
          },
          {
            "role": "v",
            "prop": "vKey",
            "type": "number",
            "required": true
          }
        ]
      },
      "intents": [
        "flow"
      ],
      "props": [
        {
          "name": "xKey",
          "reflex": "x_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'x'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "yKey",
          "reflex": "y_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'y'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "uKey",
          "reflex": "u_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'u'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "vKey",
          "reflex": "v_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "'v'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "scale",
          "reflex": "scale",
          "type": "number",
          "optional": true,
          "doc": "Arrow length per unit of magnitude; fitted to the grid by default."
        }
      ],
      "demo": "VECTOR_FIELD_CHART_DEMO",
      "demoKeys": {
        "xKey": "x",
        "yKey": "y",
        "uKey": "u",
        "vKey": "v"
      },
      "demoSample": [
        {
          "x": 0,
          "y": 0,
          "u": 0.852,
          "v": -1.246
        },
        {
          "x": 1,
          "y": 0,
          "u": 0.967,
          "v": -1.264
        },
        {
          "x": 2,
          "y": 0,
          "u": 1.097,
          "v": -1.266
        }
      ],
      "stale": "0.7.0"
    },
    {
      "slug": "network-chart",
      "names": {
        "react": "NetworkChart",
        "vue": "SpNetworkChart",
        "angular": "sp-network-chart",
        "reflex": "network_chart"
      },
      "imports": {
        "react": "@silverpoint/react/network-chart",
        "vue": "@silverpoint/vue/network-chart",
        "angular": "@silverpoint/angular/network-chart",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "fields-networks",
      "summary": "A node-link graph.",
      "data": {
        "shape": "links",
        "fields": [
          {
            "role": "source",
            "prop": "sourceKey",
            "type": "string",
            "required": true
          },
          {
            "role": "target",
            "prop": "targetKey",
            "type": "string",
            "required": true
          },
          {
            "role": "value",
            "prop": "valueKey",
            "type": "number",
            "required": false
          }
        ]
      },
      "intents": [
        "network",
        "flow"
      ],
      "props": [
        {
          "name": "sourceKey",
          "reflex": "source_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'source'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "targetKey",
          "reflex": "target_key",
          "type": "Accessor<string>",
          "optional": true,
          "default": "'target'",
          "doc": "Ignored without `data`."
        },
        {
          "name": "valueKey",
          "reflex": "value_key",
          "type": "Accessor<number | null | undefined>",
          "optional": true,
          "default": "1",
          "doc": "1 by default. Ignored without `data`."
        },
        {
          "name": "nodes",
          "reflex": "nodes",
          "type": "readonly NetworkNode[]",
          "optional": true,
          "doc": "The nodes, as data; the distinct ends of the links by default. Ignored without `data`."
        },
        {
          "name": "iterations",
          "reflex": "iterations",
          "type": "number",
          "optional": true,
          "default": "300",
          "doc": "Layout iterations; 300 by default."
        }
      ],
      "demo": "NETWORK_CHART_DEMO",
      "demoKeys": {
        "sourceKey": "source",
        "targetKey": "target",
        "valueKey": "weight"
      },
      "demoSample": [
        {
          "source": "s05",
          "target": "s02",
          "weight": 5
        },
        {
          "source": "p10",
          "target": "a06",
          "weight": 1
        },
        {
          "source": "p01",
          "target": "p07",
          "weight": 5
        }
      ],
      "stale": "0.7.0"
    }
  ],
  "components": [
    {
      "slug": "button",
      "names": {
        "react": "SpButton",
        "vue": "SpButton",
        "angular": "button[spButton]",
        "reflex": "sp_button"
      },
      "imports": {
        "react": "@silverpoint/react/ui/button",
        "vue": "@silverpoint/vue/ui/button",
        "angular": "@silverpoint/angular/ui/button",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "actions",
      "summary": "A button or a link styled as one; `primary` and `danger` variants.",
      "props": [
        {
          "name": "variant",
          "reflex": "variant",
          "type": "UiVariant",
          "optional": true,
          "default": "'default'",
          "doc": "Default `'default'`; `danger` also draws the exact ✕ glyph (REQ-310)."
        },
        {
          "name": "type",
          "reflex": "type",
          "type": "'button' | 'submit' | 'reset'",
          "optional": true,
          "default": "'button'",
          "doc": "Default `'button'`."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Not focusable, not submitted; drawn with the disabled tone."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible name of an icon-only button (REQ-319)."
        },
        {
          "name": "block",
          "reflex": "block",
          "type": "boolean",
          "optional": true,
          "doc": "Fills the width of its container."
        },
        {
          "name": "href",
          "reflex": "href",
          "type": "string",
          "optional": true,
          "doc": "Renders an `<a>`."
        }
      ],
      "events": {
        "react": [
          "onClick"
        ],
        "vue": [
          "click"
        ],
        "angular": []
      },
      "slots": {
        "react": [
          "children"
        ],
        "vue": [
          "default"
        ],
        "angular": [
          "content"
        ]
      },
      "states": [
        "default",
        "primary",
        "danger",
        "disabled"
      ],
      "demo": {
        "content": "Default"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "input",
      "names": {
        "react": "SpInput",
        "vue": "SpInput",
        "angular": "sp-input",
        "reflex": "sp_input"
      },
      "imports": {
        "react": "@silverpoint/react/ui/input",
        "vue": "@silverpoint/vue/ui/input",
        "angular": "@silverpoint/angular/ui/input",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-entry",
      "summary": "A labelled text field with an optional message and an invalid state.",
      "props": [
        {
          "name": "type",
          "reflex": "type",
          "type": "'text' | 'search' | 'email' | 'url' | 'tel' | 'password' | 'number'",
          "optional": true,
          "default": "'text'",
          "doc": "Native input type. Default `'text'`."
        },
        {
          "name": "placeholder",
          "reflex": "placeholder",
          "type": "string",
          "optional": true,
          "doc": "Hint shown while empty; not a substitute for the accessible name."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Form field name; the native input submits under it (REQ-323)."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Not focusable and not submitted."
        },
        {
          "name": "readOnly",
          "reflex": "read_only",
          "type": "boolean",
          "optional": true,
          "doc": "Focusable and submitted, but not editable."
        },
        {
          "name": "invalid",
          "reflex": "invalid",
          "type": "boolean",
          "optional": true,
          "doc": "Sets `aria-invalid` and draws the exact ⚠ glyph (REQ-334)."
        },
        {
          "name": "message",
          "reflex": "message",
          "type": "string",
          "optional": true,
          "doc": "Help or error text under the control, referenced by `aria-describedby` (REQ-334)."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible name, when no `<label for>` names the control."
        }
      ],
      "binding": {
        "value": {
          "react": "value + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [
          "change"
        ],
        "angular": []
      },
      "slots": {
        "react": [
          "prefix",
          "suffix"
        ],
        "vue": [
          "prefix",
          "suffix"
        ],
        "angular": [
          "spPrefix",
          "spSuffix"
        ]
      },
      "states": [
        "empty",
        "filled",
        "invalid",
        "disabled"
      ],
      "demo": {
        "label": "Search charts",
        "placeholder": "Search charts…",
        "type": "search",
        "name": "q",
        "value": ""
      },
      "stale": "0.7.0"
    },
    {
      "slug": "checkbox",
      "names": {
        "react": "SpCheckbox",
        "vue": "SpCheckbox",
        "angular": "sp-checkbox",
        "reflex": "sp_checkbox"
      },
      "imports": {
        "react": "@silverpoint/react/ui/checkbox",
        "vue": "@silverpoint/vue/ui/checkbox",
        "angular": "@silverpoint/angular/ui/checkbox",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-entry",
      "summary": "A labelled checkbox, with an indeterminate state.",
      "props": [
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": false,
          "doc": "The visible text and accessible name."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Form field name; submitted as `on` when checked."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Not focusable and not submitted."
        },
        {
          "name": "indeterminate",
          "reflex": "indeterminate",
          "type": "boolean",
          "optional": true,
          "doc": "Draws the exact dash and sets the native `indeterminate` state."
        }
      ],
      "binding": {
        "value": {
          "react": "checked + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [
          "change"
        ],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "unchecked",
        "checked",
        "indeterminate",
        "disabled"
      ],
      "demo": {
        "label": "Legend",
        "name": "legend",
        "value": false
      },
      "stale": "0.7.0"
    },
    {
      "slug": "radio-group",
      "names": {
        "react": "SpRadioGroup",
        "vue": "SpRadioGroup",
        "angular": "sp-radio-group",
        "reflex": "sp_radio_group"
      },
      "imports": {
        "react": "@silverpoint/react/ui/radio-group",
        "vue": "@silverpoint/vue/ui/radio-group",
        "angular": "@silverpoint/angular/ui/radio-group",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-entry",
      "summary": "One choice among a few, as a fieldset of radios.",
      "props": [
        {
          "name": "items",
          "reflex": "items",
          "type": "readonly UiItem[]",
          "optional": false,
          "doc": "The choices; each a native radio. Keys are unique (REQ-325)."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": false,
          "doc": "Required: the native radios submit under it (REQ-323)."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": false,
          "doc": "The group's name, its `<legend>`."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "UiOrientation",
          "optional": true,
          "default": "'vertical'",
          "doc": "Default `'vertical'`."
        }
      ],
      "binding": {
        "value": {
          "react": "value + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [
          "change"
        ],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "selected",
        "disabled-item"
      ],
      "demo": {
        "label": "Ground",
        "name": "ground",
        "items": [
          {
            "key": "silverpoint",
            "label": "silverpoint"
          },
          {
            "key": "cyanotype",
            "label": "cyanotype"
          }
        ],
        "value": "silverpoint",
        "orientation": "horizontal"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "switch",
      "names": {
        "react": "SpSwitch",
        "vue": "SpSwitch",
        "angular": "sp-switch",
        "reflex": "sp_switch"
      },
      "imports": {
        "react": "@silverpoint/react/ui/switch",
        "vue": "@silverpoint/vue/ui/switch",
        "angular": "@silverpoint/angular/ui/switch",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-entry",
      "summary": "An on/off toggle with the switch role.",
      "props": [
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": false,
          "doc": "The visible text and accessible name."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Form field name; submitted as `on` when on."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Not focusable and not submitted."
        }
      ],
      "binding": {
        "value": {
          "react": "checked + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [
          "change"
        ],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "off",
        "on",
        "disabled"
      ],
      "demo": {
        "label": "Linked hover",
        "name": "linked",
        "value": false
      },
      "stale": "0.7.0"
    },
    {
      "slug": "slider",
      "names": {
        "react": "SpSlider",
        "vue": "SpSlider",
        "angular": "sp-slider",
        "reflex": "sp_slider"
      },
      "imports": {
        "react": "@silverpoint/react/ui/slider",
        "vue": "@silverpoint/vue/ui/slider",
        "angular": "@silverpoint/angular/ui/slider",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-entry",
      "summary": "A value on a range, with optional marks.",
      "props": [
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": false,
          "doc": "Accessible name of the native range input."
        },
        {
          "name": "min",
          "reflex": "min",
          "type": "number",
          "optional": true,
          "default": "0",
          "doc": "Default `0`."
        },
        {
          "name": "max",
          "reflex": "max",
          "type": "number",
          "optional": true,
          "default": "100",
          "doc": "Default `100`."
        },
        {
          "name": "step",
          "reflex": "step",
          "type": "number",
          "optional": true,
          "default": "1",
          "doc": "Default `1`."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Form field name; the native input submits under it."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Not focusable and not submitted."
        },
        {
          "name": "marks",
          "reflex": "marks",
          "type": "readonly number[]",
          "optional": true,
          "doc": "Values on the rail that get a labelled mark."
        }
      ],
      "binding": {
        "value": {
          "react": "value + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [
          "change"
        ],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "marks",
        "disabled"
      ],
      "demo": {
        "label": "Volume",
        "name": "volume",
        "value": 30,
        "marks": [
          0,
          25,
          50,
          75,
          100
        ]
      },
      "stale": "0.7.0"
    },
    {
      "slug": "rate",
      "names": {
        "react": "SpRate",
        "vue": "SpRate",
        "angular": "sp-rate",
        "reflex": "sp_rate"
      },
      "imports": {
        "react": "@silverpoint/react/ui/rate",
        "vue": "@silverpoint/vue/ui/rate",
        "angular": "@silverpoint/angular/ui/rate",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-entry",
      "summary": "A rating from 1 to `count`, optionally read-only.",
      "props": [
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": false,
          "doc": "The group's name, its `<legend>`."
        },
        {
          "name": "count",
          "reflex": "count",
          "type": "number",
          "optional": true,
          "default": "5",
          "doc": "Default `5`, in 1..10; each mark an exact lozenge."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Form field name; the native radios submit under it."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Not focusable and not submitted."
        },
        {
          "name": "readOnly",
          "reflex": "read_only",
          "type": "boolean",
          "optional": true,
          "doc": "Shows the value; the keyboard and the pointer do not change it."
        }
      ],
      "binding": {
        "value": {
          "react": "value + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [
          "change"
        ],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "three",
        "read-only"
      ],
      "demo": {
        "label": "Quality",
        "name": "quality",
        "value": 3,
        "count": 5
      },
      "stale": "0.7.0"
    },
    {
      "slug": "segmented",
      "names": {
        "react": "SpSegmented",
        "vue": "SpSegmented",
        "angular": "sp-segmented",
        "reflex": "sp_segmented"
      },
      "imports": {
        "react": "@silverpoint/react/ui/segmented",
        "vue": "@silverpoint/vue/ui/segmented",
        "angular": "@silverpoint/angular/ui/segmented",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-entry",
      "summary": "One choice among a few, as joined segments.",
      "props": [
        {
          "name": "items",
          "reflex": "items",
          "type": "readonly UiItem[]",
          "optional": false,
          "doc": "The options; each a native radio. Keys are unique (REQ-325)."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": false,
          "doc": "The control's name, its `<legend>`."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Form field name; the native radios submit under it."
        },
        {
          "name": "block",
          "reflex": "block",
          "type": "boolean",
          "optional": true,
          "doc": "Fills the width of its container."
        }
      ],
      "binding": {
        "value": {
          "react": "value + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [
          "change"
        ],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "first",
        "middle"
      ],
      "demo": {
        "label": "Period",
        "name": "period",
        "items": [
          {
            "key": "day",
            "label": "Day"
          },
          {
            "key": "week",
            "label": "Week"
          },
          {
            "key": "month",
            "label": "Month"
          },
          {
            "key": "year",
            "label": "Year"
          }
        ],
        "value": "day"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "tabs",
      "names": {
        "react": "SpTabs",
        "vue": "SpTabs",
        "angular": "sp-tabs",
        "reflex": "sp_tabs"
      },
      "imports": {
        "react": "@silverpoint/react/ui/tabs",
        "vue": "@silverpoint/vue/ui/tabs",
        "angular": "@silverpoint/angular/ui/tabs",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "navigation",
      "summary": "Tabs and their panels (`SpTabPanel`), with automatic or manual activation.",
      "props": [
        {
          "name": "items",
          "reflex": "items",
          "type": "readonly UiItem[]",
          "optional": false,
          "doc": "The tabs; a disabled one is skipped by the arrows. Keys are unique (REQ-325)."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible name of the tab list."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "UiOrientation",
          "optional": true,
          "default": "'horizontal'",
          "doc": "Default `'horizontal'`."
        },
        {
          "name": "activation",
          "reflex": "activation",
          "type": "'automatic' | 'manual'",
          "optional": true,
          "default": "'automatic'",
          "doc": "Default `'automatic'`: a tab is selected as focus reaches it."
        }
      ],
      "binding": {
        "value": {
          "react": "value + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [
          "change"
        ],
        "angular": []
      },
      "slots": {
        "react": [
          "children"
        ],
        "vue": [
          "default"
        ],
        "angular": [
          "content"
        ]
      },
      "states": [
        "first",
        "disabled-tab"
      ],
      "demo": {
        "label": "Views",
        "items": [
          {
            "key": "overview",
            "label": "Overview"
          },
          {
            "key": "traffic",
            "label": "Traffic"
          },
          {
            "key": "errors",
            "label": "Errors"
          },
          {
            "key": "settings",
            "label": "Settings"
          }
        ],
        "value": "overview"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "steps",
      "names": {
        "react": "SpSteps",
        "vue": "SpSteps",
        "angular": "sp-steps",
        "reflex": "sp_steps"
      },
      "imports": {
        "react": "@silverpoint/react/ui/steps",
        "vue": "@silverpoint/vue/ui/steps",
        "angular": "@silverpoint/angular/ui/steps",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "navigation",
      "summary": "The steps of a process, with the current one and an error state.",
      "props": [
        {
          "name": "items",
          "reflex": "items",
          "type": "readonly StepItem[]",
          "optional": false,
          "doc": "The steps, in order; a status is derived from `current` unless set."
        },
        {
          "name": "current",
          "reflex": "current",
          "type": "number",
          "optional": false,
          "doc": "0-based."
        },
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "UiOrientation",
          "optional": true,
          "default": "'horizontal'",
          "doc": "Default `'horizontal'`."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible name of the list."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "current",
        "error"
      ],
      "demo": {
        "label": "Release",
        "items": [
          {
            "key": "install",
            "title": "Install"
          },
          {
            "key": "import",
            "title": "Import"
          },
          {
            "key": "configure",
            "title": "Configure"
          },
          {
            "key": "publish",
            "title": "Publish"
          }
        ],
        "current": 2
      },
      "stale": "0.7.0"
    },
    {
      "slug": "card",
      "names": {
        "react": "SpCard",
        "vue": "SpCard",
        "angular": "sp-card",
        "reflex": "sp_card"
      },
      "imports": {
        "react": "@silverpoint/react/ui/card",
        "vue": "@silverpoint/vue/ui/card",
        "angular": "@silverpoint/angular/ui/card",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-display",
      "summary": "A framed card with a title, an extra slot and a footer.",
      "props": [
        {
          "name": "title",
          "reflex": "title",
          "type": "string",
          "optional": true,
          "doc": "Heading of the card; without it the card is a plain container."
        },
        {
          "name": "headingLevel",
          "reflex": "heading_level",
          "type": "2 | 3 | 4 | 5 | 6",
          "optional": true,
          "default": "3",
          "doc": "Default `3`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "children",
          "extra",
          "footer"
        ],
        "vue": [
          "default",
          "extra",
          "footer"
        ],
        "angular": [
          "content",
          "spExtra",
          "spFooter"
        ]
      },
      "states": [
        "plain",
        "titled"
      ],
      "demo": {
        "content": "Hits per hour rose through the afternoon and eased at night."
      },
      "stale": "0.7.0"
    },
    {
      "slug": "tag",
      "names": {
        "react": "SpTag",
        "vue": "SpTag",
        "angular": "sp-tag",
        "reflex": "sp_tag"
      },
      "imports": {
        "react": "@silverpoint/react/ui/tag",
        "vue": "@silverpoint/vue/ui/tag",
        "angular": "@silverpoint/angular/ui/tag",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-display",
      "summary": "A short toned label, optionally closable.",
      "props": [
        {
          "name": "tone",
          "reflex": "tone",
          "type": "UiToneLevel",
          "optional": true,
          "doc": "Tonal level, default `1`."
        },
        {
          "name": "closable",
          "reflex": "closable",
          "type": "boolean",
          "optional": true,
          "doc": "Adds a native close button; each adapter raises its close event."
        },
        {
          "name": "closeLabel",
          "reflex": "close_label",
          "type": "string",
          "optional": true,
          "default": "Remove <text>",
          "doc": "Accessible name of the close button. Default `Remove <text>`."
        }
      ],
      "events": {
        "react": [
          "onClose"
        ],
        "vue": [
          "close"
        ],
        "angular": [
          "close"
        ]
      },
      "slots": {
        "react": [
          "children"
        ],
        "vue": [
          "default"
        ],
        "angular": [
          "content"
        ]
      },
      "states": [
        "tone-1",
        "closable"
      ],
      "demo": {
        "content": "draft",
        "tone": 1
      },
      "stale": "0.7.0"
    },
    {
      "slug": "badge",
      "names": {
        "react": "SpBadge",
        "vue": "SpBadge",
        "angular": "sp-badge",
        "reflex": "sp_badge"
      },
      "imports": {
        "react": "@silverpoint/react/ui/badge",
        "vue": "@silverpoint/vue/ui/badge",
        "angular": "@silverpoint/angular/ui/badge",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-display",
      "summary": "A count or a dot over its content.",
      "props": [
        {
          "name": "count",
          "reflex": "count",
          "type": "number",
          "optional": true,
          "doc": "The number shown, up to `max`."
        },
        {
          "name": "max",
          "reflex": "max",
          "type": "number",
          "optional": true,
          "default": "99",
          "doc": "Default `99`; above it the badge reads `99+`."
        },
        {
          "name": "dot",
          "reflex": "dot",
          "type": "boolean",
          "optional": true,
          "doc": "A dot with no number."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible text of the badge, e.g. `unread messages`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "children"
        ],
        "vue": [
          "default"
        ],
        "angular": [
          "content"
        ]
      },
      "states": [
        "count",
        "dot",
        "overflow"
      ],
      "demo": {
        "content": "Inbox",
        "count": 12
      },
      "stale": "0.7.0"
    },
    {
      "slug": "divider",
      "names": {
        "react": "SpDivider",
        "vue": "SpDivider",
        "angular": "sp-divider",
        "reflex": "sp_divider"
      },
      "imports": {
        "react": "@silverpoint/react/ui/divider",
        "vue": "@silverpoint/vue/ui/divider",
        "angular": "@silverpoint/angular/ui/divider",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "data-display",
      "summary": "A rule between sections, optionally with text.",
      "props": [
        {
          "name": "orientation",
          "reflex": "orientation",
          "type": "UiOrientation",
          "optional": true,
          "default": "'horizontal'",
          "doc": "Default `'horizontal'`."
        },
        {
          "name": "text",
          "reflex": "text",
          "type": "string",
          "optional": true,
          "doc": "A caption set in the rule."
        },
        {
          "name": "align",
          "reflex": "align",
          "type": "'start' | 'center' | 'end'",
          "optional": true,
          "default": "'center'",
          "doc": "Default `'center'`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "plain",
        "text"
      ],
      "demo": {},
      "stale": "0.7.0"
    },
    {
      "slug": "progress",
      "names": {
        "react": "SpProgress",
        "vue": "SpProgress",
        "angular": "sp-progress",
        "reflex": "sp_progress"
      },
      "imports": {
        "react": "@silverpoint/react/ui/progress",
        "vue": "@silverpoint/vue/ui/progress",
        "angular": "@silverpoint/angular/ui/progress",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "feedback",
      "summary": "Progress as a line or a circle, or indeterminate.",
      "props": [
        {
          "name": "value",
          "reflex": "value",
          "type": "number",
          "optional": true,
          "doc": "0..100; omitted, the progress is indeterminate."
        },
        {
          "name": "shape",
          "reflex": "shape",
          "type": "'line' | 'circle'",
          "optional": true,
          "default": "'line'",
          "doc": "Default `'line'`."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": false,
          "doc": "Accessible name (REQ-318)."
        },
        {
          "name": "showValue",
          "reflex": "show_value",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Default `true`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "line",
        "circle",
        "indeterminate"
      ],
      "demo": {
        "label": "Upload",
        "value": 40
      },
      "stale": "0.7.0"
    },
    {
      "slug": "alert",
      "names": {
        "react": "SpAlert",
        "vue": "SpAlert",
        "angular": "sp-alert",
        "reflex": "sp_alert"
      },
      "imports": {
        "react": "@silverpoint/react/ui/alert",
        "vue": "@silverpoint/vue/ui/alert",
        "angular": "@silverpoint/angular/ui/alert",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "feedback",
      "summary": "An info, success, warning or error message, optionally closable.",
      "props": [
        {
          "name": "kind",
          "reflex": "kind",
          "type": "AlertKind",
          "optional": true,
          "default": "'info'",
          "doc": "Default `'info'`."
        },
        {
          "name": "title",
          "reflex": "title",
          "type": "string",
          "optional": true,
          "doc": "Bold first line of the alert."
        },
        {
          "name": "closable",
          "reflex": "closable",
          "type": "boolean",
          "optional": true,
          "doc": "Adds a native close button; each adapter raises its close event."
        },
        {
          "name": "closeLabel",
          "reflex": "close_label",
          "type": "string",
          "optional": true,
          "default": "'Close'",
          "doc": "Accessible name of the close button. Default `'Close'`."
        }
      ],
      "events": {
        "react": [
          "onClose"
        ],
        "vue": [
          "close"
        ],
        "angular": [
          "close"
        ]
      },
      "slots": {
        "react": [
          "children"
        ],
        "vue": [
          "default"
        ],
        "angular": [
          "content"
        ]
      },
      "states": [
        "info",
        "success",
        "warning",
        "error"
      ],
      "demo": {
        "kind": "info",
        "title": "New ground available",
        "content": "cyanotype ships in 0.2.0."
      },
      "stale": "0.7.0"
    },
    {
      "slug": "skeleton",
      "names": {
        "react": "SpSkeleton",
        "vue": "SpSkeleton",
        "angular": "sp-skeleton",
        "reflex": "sp_skeleton"
      },
      "imports": {
        "react": "@silverpoint/react/ui/skeleton",
        "vue": "@silverpoint/vue/ui/skeleton",
        "angular": "@silverpoint/angular/ui/skeleton",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "ui",
      "group": "feedback",
      "summary": "A placeholder for content that is loading.",
      "props": [
        {
          "name": "lines",
          "reflex": "lines",
          "type": "number",
          "optional": true,
          "default": "3",
          "doc": "Default `3`, in 1..8."
        },
        {
          "name": "avatar",
          "reflex": "avatar",
          "type": "boolean",
          "optional": true,
          "doc": "Draws an avatar placeholder before the lines."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "default": "'Loading'",
          "doc": "Default `'Loading'`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "paragraph",
        "avatar"
      ],
      "demo": {
        "lines": 3
      },
      "stale": "0.7.0"
    },
    {
      "slug": "surface",
      "names": {
        "react": "SpSurface",
        "vue": "SpSurface",
        "angular": "[spSurface]",
        "reflex": "sp_surface"
      },
      "imports": {
        "react": "@silverpoint/react/ui/surface",
        "vue": "@silverpoint/vue/ui/surface",
        "angular": "@silverpoint/angular/ui/surface",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "building-blocks",
      "summary": "A framed, toned surface to build your own components on.",
      "props": [
        {
          "name": "as",
          "type": "string",
          "optional": true,
          "default": "'div'",
          "doc": "The element, a lowercase HTML tag name. Default `'div'`."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Adds the class `sp-<name>`, a lowercase ident."
        },
        {
          "name": "frame",
          "reflex": "frame",
          "type": "UiFrameKind",
          "optional": true,
          "doc": "Draws a frame of that kind."
        },
        {
          "name": "tone",
          "reflex": "tone",
          "type": "UiToneLevel | string",
          "optional": true,
          "doc": "Lays a tone: a level 1-4 of the ramp, or a state (`selected`, `primary`…)."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "children"
        ],
        "vue": [
          "default"
        ],
        "angular": [
          "content"
        ]
      },
      "states": [
        "frame-card",
        "tone-2"
      ],
      "demo": {
        "frame": "card",
        "content": "A surface takes the ground: its substrate, its ink and a hand-drawn frame."
      },
      "stale": "0.7.0"
    },
    {
      "slug": "glyph",
      "names": {
        "react": "SpGlyph",
        "vue": "SpGlyph",
        "angular": "sp-glyph",
        "reflex": "sp_glyph"
      },
      "imports": {
        "react": "@silverpoint/react/ui/glyph",
        "vue": "@silverpoint/vue/ui/glyph",
        "angular": "@silverpoint/angular/ui/glyph",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "building-blocks",
      "summary": "One of the exact glyphs the components draw (tick, cross, arrows, chevrons…).",
      "props": [
        {
          "name": "glyph",
          "reflex": "glyph",
          "type": "string",
          "optional": false,
          "doc": "A key of `UI_GLYPHS`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "all"
      ],
      "demo": {
        "glyph": "tick"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "table",
      "names": {
        "react": "SpTable",
        "vue": "SpTable",
        "angular": "sp-table",
        "reflex": "sp_table"
      },
      "imports": {
        "react": "@silverpoint/react/ui/table",
        "vue": "@silverpoint/vue/ui/table",
        "angular": "@silverpoint/angular/ui/table",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "data-display",
      "summary": "A data table with sortable columns, stripes and an empty state.",
      "props": [
        {
          "name": "columns",
          "reflex": "columns",
          "type": "readonly TableColumn[]",
          "optional": false,
          "doc": "The columns, in order; each names the key it reads from a row."
        },
        {
          "name": "data",
          "reflex": "data",
          "type": "readonly Readonly<Record<string, unknown>>[]",
          "optional": false,
          "doc": "The rows, drawn as given: the consumer sorts them (DD-040)."
        },
        {
          "name": "caption",
          "reflex": "caption",
          "type": "string",
          "optional": true,
          "doc": "The table's `<caption>`, its accessible name."
        },
        {
          "name": "sortKey",
          "reflex": "sort_key",
          "type": "string",
          "optional": true,
          "doc": "A sortable column's key; another key sorts nothing, silently."
        },
        {
          "name": "sortOrder",
          "reflex": "sort_order",
          "type": "'asc' | 'desc'",
          "optional": true,
          "default": "'asc'",
          "doc": "Default `'asc'`."
        },
        {
          "name": "striped",
          "reflex": "striped",
          "type": "boolean",
          "optional": true,
          "default": "false",
          "doc": "Default `false`."
        },
        {
          "name": "hoverable",
          "reflex": "hoverable",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Default `true`."
        },
        {
          "name": "bordered",
          "reflex": "bordered",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Default `true`."
        },
        {
          "name": "emptyText",
          "reflex": "empty_text",
          "type": "string",
          "optional": true,
          "default": "'No data'",
          "doc": "Default `'No data'`."
        },
        {
          "name": "rowKey",
          "reflex": "row_key",
          "type": "string",
          "optional": true,
          "doc": "The column whose value keys each row."
        }
      ],
      "events": {
        "react": [
          "onSort"
        ],
        "vue": [
          "sort"
        ],
        "angular": [
          "sort"
        ]
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "plain",
        "sorted-striped",
        "empty"
      ],
      "demo": {
        "caption": "Orders",
        "columns": [
          {
            "key": "order",
            "title": "Order"
          },
          {
            "key": "customer",
            "title": "Customer",
            "sortable": true
          },
          {
            "key": "status",
            "title": "Status"
          },
          {
            "key": "amount",
            "title": "Amount",
            "align": "end",
            "sortable": true
          }
        ],
        "data": [
          {
            "order": "1042",
            "customer": "Ada Lovelace",
            "status": "Shipped",
            "amount": 128
          },
          {
            "order": "1043",
            "customer": "Grace Hopper",
            "status": "Packed",
            "amount": 64.5
          },
          {
            "order": "1044",
            "customer": "Alan Turing",
            "status": "Paid",
            "amount": 312
          },
          {
            "order": "1045",
            "customer": "Emmy Noether",
            "status": "Placed",
            "amount": 18.25
          },
          {
            "order": "1046",
            "customer": "Kurt Gödel",
            "status": "Shipped",
            "amount": 96
          }
        ],
        "rowKey": "order"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "pagination",
      "names": {
        "react": "SpPagination",
        "vue": "SpPagination",
        "angular": "sp-pagination",
        "reflex": "sp_pagination"
      },
      "imports": {
        "react": "@silverpoint/react/ui/pagination",
        "vue": "@silverpoint/vue/ui/pagination",
        "angular": "@silverpoint/angular/ui/pagination",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "navigation",
      "summary": "Page navigation with a current page, siblings and an optional total.",
      "props": [
        {
          "name": "total",
          "reflex": "total",
          "type": "number",
          "optional": false,
          "doc": "The number of items paged over."
        },
        {
          "name": "pageSize",
          "reflex": "page_size",
          "type": "number",
          "optional": true,
          "default": "10",
          "doc": "Default `10`."
        },
        {
          "name": "siblings",
          "reflex": "siblings",
          "type": "number",
          "optional": true,
          "default": "1",
          "doc": "Pages shown on each side of the current one. Default `1`."
        },
        {
          "name": "showTotal",
          "reflex": "show_total",
          "type": "boolean",
          "optional": true,
          "default": "false",
          "doc": "Default `false`."
        },
        {
          "name": "totalTemplate",
          "reflex": "total_template",
          "type": "string",
          "optional": true,
          "default": "'{start}–{end} of {total}'",
          "doc": "Default `'{start}–{end} of {total}'`."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "default": "'Pagination'",
          "doc": "Default `'Pagination'`."
        },
        {
          "name": "previousLabel",
          "reflex": "previous_label",
          "type": "string",
          "optional": true,
          "default": "'Previous page'",
          "doc": "Default `'Previous page'`."
        },
        {
          "name": "nextLabel",
          "reflex": "next_label",
          "type": "string",
          "optional": true,
          "default": "'Next page'",
          "doc": "Default `'Next page'`."
        },
        {
          "name": "pageLabel",
          "reflex": "page_label",
          "type": "string",
          "optional": true,
          "default": "'Page'",
          "doc": "Default `'Page'`."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Every page button disabled."
        }
      ],
      "binding": {
        "value": {
          "react": "current + onChange",
          "vue": "v-model:current",
          "angular": "[(current)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "middle",
        "total"
      ],
      "demo": {
        "total": 200,
        "pageSize": 10,
        "current": 10
      },
      "stale": "0.7.0"
    },
    {
      "slug": "breadcrumb",
      "names": {
        "react": "SpBreadcrumb",
        "vue": "SpBreadcrumb",
        "angular": "sp-breadcrumb",
        "reflex": "sp_breadcrumb"
      },
      "imports": {
        "react": "@silverpoint/react/ui/breadcrumb",
        "vue": "@silverpoint/vue/ui/breadcrumb",
        "angular": "@silverpoint/angular/ui/breadcrumb",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "navigation",
      "summary": "The trail of pages to the current one.",
      "props": [
        {
          "name": "items",
          "reflex": "items",
          "type": "readonly BreadcrumbItem[]",
          "optional": false,
          "doc": "The last item is the current page."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "default": "'Breadcrumb'",
          "doc": "Default `'Breadcrumb'`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "three"
      ],
      "demo": {
        "items": [
          {
            "key": "home",
            "label": "Home",
            "href": "/"
          },
          {
            "key": "orders",
            "label": "Orders",
            "href": "/orders"
          },
          {
            "key": "1042",
            "label": "Order 1042"
          }
        ]
      },
      "stale": "0.7.0"
    },
    {
      "slug": "avatar",
      "names": {
        "react": "SpAvatar",
        "vue": "SpAvatar",
        "angular": "sp-avatar",
        "reflex": "sp_avatar"
      },
      "imports": {
        "react": "@silverpoint/react/ui/avatar",
        "vue": "@silverpoint/vue/ui/avatar",
        "angular": "@silverpoint/angular/ui/avatar",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "data-display",
      "summary": "A picture or initials in a round or square frame; `SpAvatarGroup` stacks several.",
      "props": [
        {
          "name": "src",
          "reflex": "src",
          "type": "string",
          "optional": true,
          "doc": "An image; the initials are drawn without one."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "The person's name: the accessible name and the source of the initials."
        },
        {
          "name": "initials",
          "reflex": "initials",
          "type": "string",
          "optional": true,
          "doc": "Overrides the initials derived from `name`."
        },
        {
          "name": "alt",
          "reflex": "alt",
          "type": "string",
          "optional": true,
          "doc": "Overrides `name` as the accessible name."
        },
        {
          "name": "shape",
          "reflex": "shape",
          "type": "'circle' | 'square'",
          "optional": true,
          "default": "'circle'",
          "doc": "Default `'circle'`."
        },
        {
          "name": "pixelSize",
          "reflex": "pixel_size",
          "type": "number",
          "optional": true,
          "doc": "Side length in px; the ground's control height when omitted."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "initials",
        "square",
        "group"
      ],
      "demo": {
        "name": "Ada Lovelace"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "statistic",
      "names": {
        "react": "SpStatistic",
        "vue": "SpStatistic",
        "angular": "sp-statistic",
        "reflex": "sp_statistic"
      },
      "imports": {
        "react": "@silverpoint/react/ui/statistic",
        "vue": "@silverpoint/vue/ui/statistic",
        "angular": "@silverpoint/angular/ui/statistic",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "data-display",
      "summary": "A titled figure with a prefix, a suffix and an optional trend.",
      "props": [
        {
          "name": "title",
          "reflex": "title",
          "type": "string",
          "optional": false,
          "doc": "The label above the value."
        },
        {
          "name": "value",
          "reflex": "value",
          "type": "string | number",
          "optional": false,
          "doc": "Printed as given."
        },
        {
          "name": "prefix",
          "reflex": "prefix",
          "type": "string",
          "optional": true,
          "doc": "Printed before the value (`$`)."
        },
        {
          "name": "suffix",
          "reflex": "suffix",
          "type": "string",
          "optional": true,
          "doc": "Printed after the value (`%`)."
        },
        {
          "name": "trend",
          "reflex": "trend",
          "type": "'up' | 'down'",
          "optional": true,
          "doc": "Draws the exact ↑ or ↓ glyph beside the delta."
        },
        {
          "name": "delta",
          "reflex": "delta",
          "type": "string",
          "optional": true,
          "doc": "The change, as text (`+4.2%`)."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "plain",
        "trend-down"
      ],
      "demo": {
        "title": "Orders",
        "value": 1284
      },
      "stale": "0.7.0"
    },
    {
      "slug": "descriptions",
      "names": {
        "react": "SpDescriptions",
        "vue": "SpDescriptions",
        "angular": "sp-descriptions",
        "reflex": "sp_descriptions"
      },
      "imports": {
        "react": "@silverpoint/react/ui/descriptions",
        "vue": "@silverpoint/vue/ui/descriptions",
        "angular": "@silverpoint/angular/ui/descriptions",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "data-display",
      "summary": "Label and value pairs as a description list.",
      "props": [
        {
          "name": "items",
          "reflex": "items",
          "type": "readonly DescriptionItem[]",
          "optional": false,
          "doc": "The label–value pairs, a `<dl>`. Keys, when given, are unique (REQ-325)."
        },
        {
          "name": "title",
          "reflex": "title",
          "type": "string",
          "optional": true,
          "doc": "A heading above the list, at `headingLevel`."
        },
        {
          "name": "columns",
          "reflex": "columns",
          "type": "number",
          "optional": true,
          "default": "3",
          "doc": "Default `3`, in 1..6."
        },
        {
          "name": "bordered",
          "reflex": "bordered",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Default `true`."
        },
        {
          "name": "headingLevel",
          "reflex": "heading_level",
          "type": "2 | 3 | 4 | 5 | 6",
          "optional": true,
          "default": "3",
          "doc": "Default `3`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "bordered",
        "plain"
      ],
      "demo": {
        "title": "Order 1042",
        "items": [
          {
            "key": "customer",
            "label": "Customer",
            "value": "Ada Lovelace"
          },
          {
            "key": "status",
            "label": "Status",
            "value": "Shipped"
          },
          {
            "key": "amount",
            "label": "Amount",
            "value": "128.00"
          },
          {
            "key": "placed",
            "label": "Placed",
            "value": "14 October 2026"
          }
        ],
        "columns": 2
      },
      "stale": "0.7.0"
    },
    {
      "slug": "timeline-list",
      "names": {
        "react": "SpTimelineList",
        "vue": "SpTimelineList",
        "angular": "sp-timeline-list",
        "reflex": "sp_timeline_list"
      },
      "imports": {
        "react": "@silverpoint/react/ui/timeline-list",
        "vue": "@silverpoint/vue/ui/timeline-list",
        "angular": "@silverpoint/angular/ui/timeline-list",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "data-display",
      "summary": "Events in order, each done, current, pending or in error.",
      "props": [
        {
          "name": "items",
          "reflex": "items",
          "type": "readonly TimelineListItem[]",
          "optional": false,
          "doc": "The events, in reading order."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible name of the list."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "mixed"
      ],
      "demo": {
        "label": "Order history",
        "items": [
          {
            "key": "placed",
            "title": "Placed",
            "time": "14 Oct, 09:12",
            "description": "Two prints, one framed."
          },
          {
            "key": "paid",
            "title": "Payment",
            "time": "14 Oct, 09:14",
            "description": "Card declined; paid on the second try.",
            "status": "error"
          },
          {
            "key": "packed",
            "title": "Packed",
            "time": "15 Oct, 16:40",
            "status": "current"
          },
          {
            "key": "shipped",
            "title": "Shipped",
            "status": "pending"
          }
        ]
      },
      "stale": "0.7.0"
    },
    {
      "slug": "collapse",
      "names": {
        "react": "SpCollapse",
        "vue": "SpCollapse",
        "angular": "sp-collapse",
        "reflex": "sp_collapse"
      },
      "imports": {
        "react": "@silverpoint/react/ui/collapse",
        "vue": "@silverpoint/vue/ui/collapse",
        "angular": "@silverpoint/angular/ui/collapse",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "disclosure",
      "summary": "Disclosure panels (`SpCollapseItem`), optionally as an accordion.",
      "props": [
        {
          "name": "accordion",
          "reflex": "accordion",
          "type": "boolean",
          "optional": true,
          "default": "false",
          "doc": "One item open at a time, natively (`<details name>`). Default `false`."
        },
        {
          "name": "bordered",
          "reflex": "bordered",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Default `true`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "children"
        ],
        "vue": [
          "default"
        ],
        "angular": [
          "content"
        ]
      },
      "states": [
        "one-open",
        "accordion-disabled"
      ],
      "demo": {
        "items": [
          {
            "key": "ground",
            "title": "What is a ground?",
            "content": "The prepared surface a metal stylus can mark: bone ash, gum and a little pigment.",
            "open": true
          },
          {
            "key": "erase",
            "title": "Can a line be erased?",
            "content": "No. Every line stays, so the drawing is planned before it is drawn."
          },
          {
            "key": "tone",
            "title": "Where does the tone come from?",
            "content": "From hatching, level by level, never from transparency."
          }
        ]
      },
      "stale": "0.7.0"
    },
    {
      "slug": "empty",
      "names": {
        "react": "SpEmpty",
        "vue": "SpEmpty",
        "angular": "sp-empty",
        "reflex": "sp_empty"
      },
      "imports": {
        "react": "@silverpoint/react/ui/empty",
        "vue": "@silverpoint/vue/ui/empty",
        "angular": "@silverpoint/angular/ui/empty",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "data-display",
      "summary": "The empty state of a list or a table.",
      "props": [
        {
          "name": "description",
          "reflex": "description",
          "type": "string",
          "optional": true,
          "default": "'No data'",
          "doc": "Default `'No data'`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "extra"
        ],
        "vue": [
          "extra"
        ],
        "angular": [
          "spExtra"
        ]
      },
      "states": [
        "plain"
      ],
      "demo": {
        "description": "No orders yet"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "result",
      "names": {
        "react": "SpResult",
        "vue": "SpResult",
        "angular": "sp-result",
        "reflex": "sp_result"
      },
      "imports": {
        "react": "@silverpoint/react/ui/result",
        "vue": "@silverpoint/vue/ui/result",
        "angular": "@silverpoint/angular/ui/result",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "data-display",
      "summary": "The outcome of an action: success, error, information or warning.",
      "props": [
        {
          "name": "status",
          "reflex": "status",
          "type": "AlertKind",
          "optional": true,
          "default": "'info'",
          "doc": "Default `'info'`."
        },
        {
          "name": "title",
          "reflex": "title",
          "type": "string",
          "optional": false,
          "doc": "The heading, at `headingLevel`."
        },
        {
          "name": "subtitle",
          "reflex": "subtitle",
          "type": "string",
          "optional": true,
          "doc": "A paragraph under the title."
        },
        {
          "name": "headingLevel",
          "reflex": "heading_level",
          "type": "2 | 3 | 4 | 5 | 6",
          "optional": true,
          "default": "3",
          "doc": "Default `3`."
        }
      ],
      "events": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "extra"
        ],
        "vue": [
          "extra"
        ],
        "angular": [
          "spExtra"
        ]
      },
      "states": [
        "success",
        "error"
      ],
      "demo": {
        "status": "success",
        "title": "Order placed",
        "subtitle": "Order 1042 is on its way to the workshop."
      },
      "stale": "0.7.0"
    },
    {
      "slug": "textarea",
      "names": {
        "react": "SpTextarea",
        "vue": "SpTextarea",
        "angular": "sp-textarea",
        "reflex": "sp_textarea"
      },
      "imports": {
        "react": "@silverpoint/react/ui/textarea",
        "vue": "@silverpoint/vue/ui/textarea",
        "angular": "@silverpoint/angular/ui/textarea",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "data-entry",
      "summary": "A multi-line text field with a counter and an invalid state.",
      "props": [
        {
          "name": "rows",
          "reflex": "rows",
          "type": "number",
          "optional": true,
          "default": "3",
          "doc": "Default `3`."
        },
        {
          "name": "placeholder",
          "reflex": "placeholder",
          "type": "string",
          "optional": true,
          "doc": "Hint shown while empty; not a substitute for the accessible name."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible name, when no `<label for>` names the control."
        },
        {
          "name": "message",
          "reflex": "message",
          "type": "string",
          "optional": true,
          "doc": "Help or error text under the control, referenced by `aria-describedby` (REQ-334)."
        },
        {
          "name": "invalid",
          "reflex": "invalid",
          "type": "boolean",
          "optional": true,
          "doc": "Sets `aria-invalid` and draws the exact ⚠ glyph (REQ-334)."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Not focusable and not submitted."
        },
        {
          "name": "readOnly",
          "reflex": "read_only",
          "type": "boolean",
          "optional": true,
          "doc": "Focusable and submitted, but not editable."
        },
        {
          "name": "maxLength",
          "reflex": "max_length",
          "type": "number",
          "optional": true,
          "doc": "The native limit; the counter shows it with `showCount`."
        },
        {
          "name": "showCount",
          "reflex": "show_count",
          "type": "boolean",
          "optional": true,
          "default": "false",
          "doc": "Default `false`."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Form field name; the native textarea submits under it (REQ-323)."
        }
      ],
      "binding": {
        "value": {
          "react": "value + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [
          "change"
        ],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "count",
        "invalid"
      ],
      "demo": {
        "label": "Notes",
        "name": "notes",
        "value": "Leave it at the door.",
        "maxLength": 120,
        "showCount": true
      },
      "stale": "0.7.0"
    },
    {
      "slug": "input-number",
      "names": {
        "react": "SpInputNumber",
        "vue": "SpInputNumber",
        "angular": "sp-input-number",
        "reflex": "sp_input_number"
      },
      "imports": {
        "react": "@silverpoint/react/ui/input-number",
        "vue": "@silverpoint/vue/ui/input-number",
        "angular": "@silverpoint/angular/ui/input-number",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "composed",
      "group": "data-entry",
      "summary": "A number field with steppers, bounds and precision.",
      "props": [
        {
          "name": "min",
          "reflex": "min",
          "type": "number",
          "optional": true,
          "doc": "The lowest value; the value is clamped to it (REQ-485)."
        },
        {
          "name": "max",
          "reflex": "max",
          "type": "number",
          "optional": true,
          "doc": "The highest value; the value is clamped to it (REQ-485)."
        },
        {
          "name": "step",
          "reflex": "step",
          "type": "number",
          "optional": true,
          "default": "1",
          "doc": "Default `1`."
        },
        {
          "name": "precision",
          "reflex": "precision",
          "type": "number",
          "optional": true,
          "doc": "Decimals."
        },
        {
          "name": "placeholder",
          "reflex": "placeholder",
          "type": "string",
          "optional": true,
          "doc": "Hint shown while empty; not a substitute for the accessible name."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible name, when no `<label for>` names the control."
        },
        {
          "name": "message",
          "reflex": "message",
          "type": "string",
          "optional": true,
          "doc": "Help or error text under the control, referenced by `aria-describedby` (REQ-334)."
        },
        {
          "name": "invalid",
          "reflex": "invalid",
          "type": "boolean",
          "optional": true,
          "doc": "Sets `aria-invalid` and draws the exact ⚠ glyph (REQ-334)."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Not focusable and not submitted; the steppers are disabled too."
        },
        {
          "name": "readOnly",
          "reflex": "read_only",
          "type": "boolean",
          "optional": true,
          "doc": "Focusable and submitted, but not editable."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Form field name; the native input submits under it (REQ-323)."
        },
        {
          "name": "decrementLabel",
          "reflex": "decrement_label",
          "type": "string",
          "optional": true,
          "default": "'Decrease'",
          "doc": "Default `'Decrease'`."
        },
        {
          "name": "incrementLabel",
          "reflex": "increment_label",
          "type": "string",
          "optional": true,
          "default": "'Increase'",
          "doc": "Default `'Increase'`."
        }
      ],
      "binding": {
        "value": {
          "react": "value + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        }
      },
      "events": {
        "react": [
          "onChange"
        ],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "value",
        "at-min"
      ],
      "demo": {
        "label": "Quantity",
        "name": "quantity",
        "value": 3,
        "min": 1,
        "max": 10
      },
      "stale": "0.7.0"
    },
    {
      "slug": "modal",
      "names": {
        "react": "SpModal",
        "vue": "SpModal",
        "angular": "sp-modal",
        "reflex": "sp_modal"
      },
      "imports": {
        "react": "@silverpoint/react/ui/modal",
        "vue": "@silverpoint/vue/ui/modal",
        "angular": "@silverpoint/angular/ui/modal",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "overlay",
      "group": "overlays",
      "summary": "A modal dialog on the native `<dialog>`, opened by its trigger.",
      "props": [
        {
          "name": "title",
          "reflex": "title",
          "type": "string",
          "optional": true,
          "doc": "The heading, `${id}--title`, that names the dialog."
        },
        {
          "name": "description",
          "reflex": "description",
          "type": "string",
          "optional": true,
          "doc": "A paragraph, `${id}--description`, that describes the dialog."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible name without a title (REQ-501)."
        },
        {
          "name": "closable",
          "reflex": "closable",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Default `true`."
        },
        {
          "name": "closeLabel",
          "reflex": "close_label",
          "type": "string",
          "optional": true,
          "default": "'Close'",
          "doc": "Default `'Close'`."
        },
        {
          "name": "width",
          "reflex": "width",
          "type": "string",
          "optional": true,
          "default": "'520px'",
          "doc": "CSS length. Default `'520px'` (from `ui.css`)."
        },
        {
          "name": "dismissible",
          "reflex": "dismissible",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "Escape and a backdrop click close it. Default `true`."
        }
      ],
      "binding": {
        "open": {
          "react": "open + onOpenChange",
          "vue": "v-model:open",
          "angular": "[(open)]"
        }
      },
      "events": {
        "react": [
          "onOpenChange"
        ],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "children",
          "footer",
          "trigger"
        ],
        "vue": [
          "default",
          "footer",
          "trigger"
        ],
        "angular": [
          "content",
          "spFooter",
          "spTrigger"
        ]
      },
      "states": [
        "open"
      ],
      "demo": {
        "open": true,
        "trigger": "Edit order",
        "title": "Edit order",
        "description": "Order 1042, placed on 14 October.",
        "content": "Changes reach the workshop before the order is packed."
      },
      "stale": "0.7.0"
    },
    {
      "slug": "drawer",
      "names": {
        "react": "SpDrawer",
        "vue": "SpDrawer",
        "angular": "sp-drawer",
        "reflex": "sp_drawer"
      },
      "imports": {
        "react": "@silverpoint/react/ui/drawer",
        "vue": "@silverpoint/vue/ui/drawer",
        "angular": "@silverpoint/angular/ui/drawer",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "overlay",
      "group": "overlays",
      "summary": "A dialog sliding in from one side of the viewport.",
      "props": [
        {
          "name": "side",
          "reflex": "side",
          "type": "'start' | 'end' | 'top' | 'bottom'",
          "optional": true,
          "default": "'end'",
          "doc": "Default `'end'`."
        },
        {
          "name": "extent",
          "reflex": "extent",
          "type": "string",
          "optional": true,
          "default": "'380px'",
          "doc": "CSS length across the side. Default `'380px'` (start/end) or `'320px'` (top/bottom)."
        },
        {
          "name": "modal",
          "reflex": "modal",
          "type": "boolean",
          "optional": true,
          "default": "true",
          "doc": "`false` opens with `show()`. Default `true`."
        }
      ],
      "binding": {
        "open": {
          "react": "open + onOpenChange",
          "vue": "v-model:open",
          "angular": "[(open)]"
        }
      },
      "events": {
        "react": [
          "onOpenChange"
        ],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "children",
          "footer",
          "trigger"
        ],
        "vue": [
          "default",
          "footer",
          "trigger"
        ],
        "angular": [
          "content",
          "spFooter",
          "spTrigger"
        ]
      },
      "states": [
        "end-open"
      ],
      "demo": {
        "open": true,
        "side": "end",
        "trigger": "Filters",
        "title": "Filters",
        "content": "Narrow the orders by status, customer or amount."
      },
      "stale": "0.7.0"
    },
    {
      "slug": "popover",
      "names": {
        "react": "SpPopover",
        "vue": "SpPopover",
        "angular": "sp-popover",
        "reflex": "sp_popover"
      },
      "imports": {
        "react": "@silverpoint/react/ui/popover",
        "vue": "@silverpoint/vue/ui/popover",
        "angular": "@silverpoint/angular/ui/popover",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "overlay",
      "group": "overlays",
      "summary": "Non-modal content anchored to its trigger, on the Popover API.",
      "props": [
        {
          "name": "title",
          "reflex": "title",
          "type": "string",
          "optional": true,
          "doc": "A heading that names the popover."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": true,
          "doc": "Accessible name without a title."
        },
        {
          "name": "side",
          "reflex": "side",
          "type": "'top' | 'end' | 'bottom' | 'start'",
          "optional": true,
          "default": "'bottom'",
          "doc": "Default `'bottom'`."
        },
        {
          "name": "align",
          "reflex": "align",
          "type": "'start' | 'center' | 'end'",
          "optional": true,
          "default": "'center'",
          "doc": "Default `'center'`."
        },
        {
          "name": "offset",
          "reflex": "offset",
          "type": "number",
          "optional": true,
          "default": "6",
          "doc": "Default `6`."
        },
        {
          "name": "closable",
          "reflex": "closable",
          "type": "boolean",
          "optional": true,
          "default": "false",
          "doc": "Default `false`."
        },
        {
          "name": "closeLabel",
          "reflex": "close_label",
          "type": "string",
          "optional": true,
          "default": "'Close'",
          "doc": "Default `'Close'`."
        },
        {
          "name": "width",
          "reflex": "width",
          "type": "string",
          "optional": true,
          "default": "'320px'",
          "doc": "CSS length. Default `'320px'` (from `ui.css`)."
        }
      ],
      "binding": {
        "open": {
          "react": "open + onOpenChange",
          "vue": "v-model:open",
          "angular": "[(open)]"
        }
      },
      "events": {
        "react": [
          "onOpenChange"
        ],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "children",
          "trigger"
        ],
        "vue": [
          "default",
          "trigger"
        ],
        "angular": [
          "content",
          "spTrigger"
        ]
      },
      "states": [
        "open"
      ],
      "demo": {
        "open": true,
        "trigger": "Details",
        "title": "Order 1042",
        "content": "Two prints, one framed; shipped on 16 October."
      },
      "stale": "0.7.0"
    },
    {
      "slug": "tooltip",
      "names": {
        "react": "SpTooltip",
        "vue": "SpTooltip",
        "angular": "sp-tooltip",
        "reflex": "sp_tooltip"
      },
      "imports": {
        "react": "@silverpoint/react/ui/tooltip",
        "vue": "@silverpoint/vue/ui/tooltip",
        "angular": "@silverpoint/angular/ui/tooltip",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "overlay",
      "group": "overlays",
      "summary": "A short text shown on hover or focus of its trigger.",
      "props": [
        {
          "name": "text",
          "reflex": "text",
          "type": "string",
          "optional": false,
          "doc": "The tooltip, the trigger's accessible description."
        },
        {
          "name": "side",
          "reflex": "side",
          "type": "'top' | 'end' | 'bottom' | 'start'",
          "optional": true,
          "default": "'top'",
          "doc": "Default `'top'`."
        },
        {
          "name": "align",
          "reflex": "align",
          "type": "'start' | 'center' | 'end'",
          "optional": true,
          "default": "'center'",
          "doc": "Default `'center'`."
        },
        {
          "name": "offset",
          "reflex": "offset",
          "type": "number",
          "optional": true,
          "default": "6",
          "doc": "Default `6`."
        },
        {
          "name": "delay",
          "reflex": "delay",
          "type": "number",
          "optional": true,
          "default": "300",
          "doc": "Default `300` ms."
        }
      ],
      "binding": {
        "open": {
          "react": "open + onOpenChange",
          "vue": "v-model:open",
          "angular": "[(open)]"
        }
      },
      "events": {
        "react": [
          "onOpenChange"
        ],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "trigger"
        ],
        "vue": [
          "trigger"
        ],
        "angular": [
          "spTrigger"
        ]
      },
      "states": [
        "open"
      ],
      "demo": {
        "open": true,
        "trigger": "Copy id",
        "text": "Copy the order id"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "select",
      "names": {
        "react": "SpSelect",
        "vue": "SpSelect",
        "angular": "sp-select",
        "reflex": "sp_select"
      },
      "imports": {
        "react": "@silverpoint/react/ui/select",
        "vue": "@silverpoint/vue/ui/select",
        "angular": "@silverpoint/angular/ui/select",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "overlay",
      "group": "overlays",
      "summary": "A select-only combobox: one option from a list.",
      "props": [
        {
          "name": "items",
          "reflex": "items",
          "type": "readonly (string | UiItem)[]",
          "optional": false,
          "doc": "A string is its own key and label."
        },
        {
          "name": "placeholder",
          "reflex": "placeholder",
          "type": "string",
          "optional": true,
          "default": "'Select…'",
          "doc": "Default `'Select…'`."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": false,
          "doc": "Accessible name of the combobox."
        },
        {
          "name": "disabled",
          "reflex": "disabled",
          "type": "boolean",
          "optional": true,
          "doc": "Not focusable and not submitted."
        },
        {
          "name": "required",
          "reflex": "required",
          "type": "boolean",
          "optional": true,
          "doc": "Sets `aria-required` on the combobox."
        },
        {
          "name": "name",
          "reflex": "name",
          "type": "string",
          "optional": true,
          "doc": "Submits the key under this name, from a hidden input (REQ-323)."
        },
        {
          "name": "width",
          "reflex": "width",
          "type": "string",
          "optional": true,
          "default": "'180px'",
          "doc": "CSS length. Default `'180px'` (from `ui.css`)."
        }
      ],
      "binding": {
        "value": {
          "react": "value + onChange",
          "vue": "v-model",
          "angular": "[(value)]"
        },
        "open": {
          "react": "open + onOpenChange",
          "vue": "v-model:open",
          "angular": "[(open)]"
        }
      },
      "events": {
        "react": [
          "onChange",
          "onOpenChange"
        ],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [],
        "vue": [],
        "angular": []
      },
      "states": [
        "placeholder",
        "open-selected"
      ],
      "demo": {
        "label": "Status",
        "name": "status",
        "items": [
          {
            "key": "placed",
            "label": "Placed"
          },
          {
            "key": "paid",
            "label": "Paid"
          },
          {
            "key": "packed",
            "label": "Packed"
          },
          {
            "key": "shipped",
            "label": "Shipped"
          },
          {
            "key": "returned",
            "label": "Returned",
            "disabled": true
          }
        ],
        "value": null
      },
      "stale": "0.7.0"
    },
    {
      "slug": "dropdown-menu",
      "names": {
        "react": "SpDropdownMenu",
        "vue": "SpDropdownMenu",
        "angular": "sp-dropdown-menu",
        "reflex": "sp_dropdown_menu"
      },
      "imports": {
        "react": "@silverpoint/react/ui/dropdown-menu",
        "vue": "@silverpoint/vue/ui/dropdown-menu",
        "angular": "@silverpoint/angular/ui/dropdown-menu",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "overlay",
      "group": "overlays",
      "summary": "A menu of actions opened from its trigger.",
      "props": [
        {
          "name": "items",
          "reflex": "items",
          "type": "readonly MenuEntry[]",
          "optional": false,
          "doc": "Items, separators and labels, in order. Keys are unique (REQ-325)."
        },
        {
          "name": "label",
          "reflex": "label",
          "type": "string",
          "optional": false,
          "doc": "The menu's accessible name and the trigger's text when no trigger slot."
        },
        {
          "name": "side",
          "reflex": "side",
          "type": "'top' | 'end' | 'bottom' | 'start'",
          "optional": true,
          "default": "'bottom'",
          "doc": "Default `'bottom'`."
        },
        {
          "name": "align",
          "reflex": "align",
          "type": "'start' | 'center' | 'end'",
          "optional": true,
          "default": "'start'",
          "doc": "Default `'start'`."
        }
      ],
      "binding": {
        "open": {
          "react": "open + onOpenChange",
          "vue": "v-model:open",
          "angular": "[(open)]"
        }
      },
      "events": {
        "react": [
          "onOpenChange",
          "onSelect"
        ],
        "vue": [
          "select"
        ],
        "angular": [
          "select"
        ]
      },
      "slots": {
        "react": [
          "trigger"
        ],
        "vue": [
          "trigger"
        ],
        "angular": [
          "spTrigger"
        ]
      },
      "states": [
        "open"
      ],
      "demo": {
        "label": "Actions",
        "trigger": "Actions",
        "items": [
          {
            "type": "label",
            "key": "order",
            "label": "Order 1042"
          },
          {
            "key": "edit",
            "label": "Edit",
            "shortcut": "E"
          },
          {
            "key": "duplicate",
            "label": "Duplicate",
            "shortcut": "D"
          },
          {
            "key": "archive",
            "label": "Archive",
            "disabled": true
          },
          {
            "type": "separator",
            "key": "end"
          },
          {
            "key": "delete",
            "label": "Delete",
            "danger": true
          }
        ],
        "open": true,
        "active": "edit"
      },
      "stale": "0.7.0"
    },
    {
      "slug": "toast",
      "names": {
        "react": "SpToast",
        "vue": "SpToast",
        "angular": "sp-toast",
        "reflex": "sp_toast"
      },
      "imports": {
        "react": "@silverpoint/react/ui/toast",
        "vue": "@silverpoint/vue/ui/toast",
        "angular": "@silverpoint/angular/ui/toast",
        "reflex": "reflex_silverpoint_react"
      },
      "family": "overlay",
      "group": "overlays",
      "summary": "A transient message in a `SpToaster`, with an optional action.",
      "props": [
        {
          "name": "title",
          "reflex": "title",
          "type": "string",
          "optional": false,
          "doc": "The toast's first line."
        },
        {
          "name": "description",
          "reflex": "description",
          "type": "string",
          "optional": true,
          "doc": "A line under the title."
        },
        {
          "name": "kind",
          "reflex": "kind",
          "type": "AlertKind",
          "optional": true,
          "default": "'info'",
          "doc": "Default `'info'`."
        },
        {
          "name": "duration",
          "reflex": "duration",
          "type": "number",
          "optional": true,
          "doc": "ms, at least 1000, or `Infinity`; the toaster's when omitted."
        },
        {
          "name": "closeLabel",
          "reflex": "close_label",
          "type": "string",
          "optional": true,
          "default": "'Dismiss'",
          "doc": "Default `'Dismiss'`."
        }
      ],
      "binding": {
        "open": {
          "react": "open + onOpenChange",
          "vue": "v-model:open",
          "angular": "[(open)]"
        }
      },
      "events": {
        "react": [
          "onOpenChange"
        ],
        "vue": [],
        "angular": []
      },
      "slots": {
        "react": [
          "action"
        ],
        "vue": [
          "action"
        ],
        "angular": [
          "spAction"
        ]
      },
      "states": [
        "info",
        "error-action"
      ],
      "demo": {
        "kind": "info",
        "title": "Order saved",
        "description": "Order 1042 was updated.",
        "open": true
      },
      "stale": "0.7.0"
    }
  ],
  "dashboard": {
    "props": [
      {
        "name": "title",
        "reflex": "title",
        "type": "string",
        "optional": true,
        "doc": ""
      },
      {
        "name": "label",
        "reflex": "label",
        "type": "string",
        "optional": true,
        "doc": ""
      },
      {
        "name": "id",
        "type": "string",
        "optional": false,
        "doc": "Stable identifier; seeds of unnamed charts derive from it (REQ-209). Required."
      },
      {
        "name": "layout",
        "reflex": "layout",
        "type": "DashboardLayout",
        "optional": true,
        "doc": ""
      },
      {
        "name": "description",
        "reflex": "description",
        "type": "string",
        "optional": true,
        "doc": "Long description, exposed as the region's description (REQ-214)."
      },
      {
        "name": "headingLevel",
        "reflex": "heading_level",
        "type": "2 | 3 | 4 | 5 | 6",
        "optional": true,
        "default": "2",
        "doc": "Heading level of `title`. Default `2`."
      },
      {
        "name": "ssrWidth",
        "reflex": "ssr_width",
        "type": "number",
        "optional": true,
        "default": "1200",
        "doc": "Width in px used for nominal cell boxes on the server and at hydration (REQ-207). Default `1200`."
      },
      {
        "name": "link",
        "reflex": "link",
        "type": "DashboardLink",
        "optional": true,
        "doc": "Linked interaction (REQ-216); client entry points only."
      },
      {
        "name": "ground",
        "reflex": "ground",
        "type": "GroundRef",
        "optional": true,
        "doc": "Inherited by every chart inside, below the chart's own prop (REQ-212)."
      },
      {
        "name": "substrate",
        "reflex": "substrate",
        "type": "SubstrateName",
        "optional": true,
        "doc": ""
      },
      {
        "name": "mode",
        "reflex": "mode",
        "type": "InkMode",
        "optional": true,
        "doc": ""
      },
      {
        "name": "locale",
        "reflex": "locale",
        "type": "string",
        "optional": true,
        "doc": ""
      },
      {
        "name": "palette",
        "reflex": "palette",
        "type": "Palette",
        "optional": true,
        "doc": "The section's colours, written on its root and merged under every chart's and component's own (REQ-462)."
      },
      {
        "name": "className",
        "type": "string",
        "optional": true,
        "doc": ""
      }
    ],
    "layout": [
      {
        "name": "columns",
        "type": "PerBreakpoint<number>",
        "optional": true,
        "default": "{ sm: 1, md: 2, lg: 4 }",
        "doc": "Columns per breakpoint. Default `{ sm: 1, md: 2, lg: 4 }` (REQ-208)."
      },
      {
        "name": "rowHeight",
        "type": "number",
        "optional": true,
        "default": "240",
        "doc": "Height of one row unit, in px, card chrome included. Default `240`."
      },
      {
        "name": "gap",
        "type": "number",
        "optional": true,
        "default": "16",
        "doc": "Gap between cells, in px. Default `16`."
      },
      {
        "name": "cells",
        "type": "readonly DashboardCellLayout[]",
        "optional": true,
        "doc": "Cells in reading order (REQ-203). Omitted: every child, span 1."
      }
    ],
    "cell": [
      {
        "name": "id",
        "type": "string",
        "optional": false,
        "doc": "Matches `DashboardCell`'s `cell` prop; unique within the dashboard (REQ-205)."
      },
      {
        "name": "colSpan",
        "type": "PerBreakpoint<number>",
        "optional": true,
        "default": "1",
        "doc": "Default `1`. Clamped to the breakpoint's columns with `SP014` (REQ-204)."
      },
      {
        "name": "rowSpan",
        "type": "PerBreakpoint<number>",
        "optional": true,
        "default": "1",
        "doc": "Default `1`."
      }
    ],
    "names": {
      "react": "Dashboard",
      "vue": "SpDashboard",
      "angular": "sp-dashboard",
      "reflex": "dashboard"
    },
    "imports": {
      "react": "@silverpoint/react/dashboard",
      "vue": "@silverpoint/vue/dashboard",
      "angular": "@silverpoint/angular/dashboard",
      "reflex": "reflex_silverpoint_react"
    }
  },
  "grounds": [
    {
      "name": "silverpoint",
      "substrates": [
        "cream",
        "green",
        "blue",
        "ochre"
      ],
      "summary": "Metal point on prepared paper: hatched tone, a hand-inked line, cream and other prepared substrates."
    },
    {
      "name": "cyanotype",
      "substrates": [
        "prussian"
      ],
      "summary": "A contact print: a white, exact line on Prussian blue; tone is line weight, nothing is hatched."
    }
  ],
  "palettes": {
    "fields": [
      {
        "name": "substrate",
        "type": "string",
        "optional": true,
        "doc": "The prepared ground the drawing sits on."
      },
      {
        "name": "ink",
        "type": "string",
        "optional": true,
        "doc": "The main series and the frames of UI components."
      },
      {
        "name": "inkSecondary",
        "type": "string",
        "optional": true,
        "doc": "The second series and the hatch of tones."
      },
      {
        "name": "heighten",
        "type": "string",
        "optional": true,
        "doc": "White heightening on the live value (always outlined with `ink`)."
      },
      {
        "name": "rule",
        "type": "string",
        "optional": true,
        "doc": "Rules and baselines."
      },
      {
        "name": "grid",
        "type": "string",
        "optional": true,
        "doc": "Grid lines."
      },
      {
        "name": "text",
        "type": "string",
        "optional": true,
        "doc": "Large figures and primary labels."
      },
      {
        "name": "textMuted",
        "type": "string",
        "optional": true,
        "doc": "Axis labels and secondary text."
      },
      {
        "name": "focus",
        "type": "string",
        "optional": true,
        "default": "ink",
        "doc": "Focus ring of UI components; `ink` by default."
      }
    ],
    "presets": {
      "silverpoint": {
        "substrate": "#EDE7DA",
        "ink": "#5A5E65",
        "inkSecondary": "#685C4D",
        "heighten": "#FFFFFF",
        "rule": "#737A82",
        "grid": "#737A82",
        "text": "#3F4348",
        "textMuted": "#5A5E65"
      },
      "sanguine": {
        "substrate": "#F2E8DC",
        "ink": "#8A3A24",
        "inkSecondary": "#6A4A3A",
        "heighten": "#FFFFFF",
        "rule": "#9A6450",
        "grid": "#9A6450",
        "text": "#4A2216",
        "textMuted": "#7A3E2C"
      },
      "sepia": {
        "substrate": "#F0E6D2",
        "ink": "#6B4C2C",
        "inkSecondary": "#5A5148",
        "heighten": "#FFFFFF",
        "rule": "#8A6E52",
        "grid": "#8A6E52",
        "text": "#3B2A18",
        "textMuted": "#6B4C2C"
      },
      "ironGall": {
        "substrate": "#EEEAE0",
        "ink": "#3C4858",
        "inkSecondary": "#6A4E36",
        "heighten": "#FFFFFF",
        "rule": "#6C7584",
        "grid": "#6C7584",
        "text": "#232B36",
        "textMuted": "#4A5566"
      },
      "verdigris": {
        "substrate": "#E7EDE6",
        "ink": "#2C6355",
        "inkSecondary": "#65563F",
        "heighten": "#FFFFFF",
        "rule": "#5C7B71",
        "grid": "#5C7B71",
        "text": "#1F3D36",
        "textMuted": "#3E6A5E"
      },
      "indigo": {
        "substrate": "#E9EAF1",
        "ink": "#3A4884",
        "inkSecondary": "#675641",
        "heighten": "#FFFFFF",
        "rule": "#68709A",
        "grid": "#68709A",
        "text": "#232C52",
        "textMuted": "#4A5590"
      }
    }
  },
  "timeline": {
    "props": [
      {
        "name": "data",
        "reflex": "data",
        "type": "TimelineData",
        "optional": false,
        "doc": "TimelineJS's JSON: a `title` slide, the `events`, optional `eras` and `scale`."
      },
      {
        "name": "options",
        "reflex": "options",
        "type": "Readonly<Record<string, unknown>>",
        "optional": true,
        "doc": "TimelineJS options; `font` and `theme` are ignored, the skin sets both."
      },
      {
        "name": "height",
        "reflex": "height",
        "type": "string",
        "optional": true,
        "default": "'600px'",
        "doc": "A plain CSS length. Default `'600px'`."
      },
      {
        "name": "inkedFrames",
        "reflex": "inked_frames",
        "type": "boolean",
        "optional": true,
        "default": "true",
        "doc": "Lays the ground's frames and tones on TimelineJS's pieces (REQ-512). Default `true`."
      },
      {
        "name": "card",
        "reflex": "card",
        "type": "boolean",
        "optional": true,
        "default": "true",
        "doc": "Frames the whole timeline as a card. Default `true`."
      },
      {
        "name": "label",
        "reflex": "label",
        "type": "string",
        "optional": true,
        "doc": "The region's accessible name; the title's headline when omitted."
      }
    ],
    "names": {
      "react": "SpTimeline",
      "vue": "SpTimeline",
      "angular": "sp-timeline",
      "reflex": "sp_timeline"
    },
    "imports": {
      "react": "@silverpoint/react/timeline",
      "vue": "@silverpoint/vue/timeline",
      "angular": "@silverpoint/angular/timeline",
      "reflex": "reflex_silverpoint_react"
    },
    "peer": "@knight-lab/timelinejs@^3.9.13"
  },
  "diagnostics": [
    {
      "code": "SP001",
      "severity": "warn",
      "req": "REQ-007",
      "what": "the dataset is empty; the ground's empty state is drawn",
      "todo": "Pass at least one row, or omit `data` to see the demo dataset"
    },
    {
      "code": "SP002",
      "severity": "warn",
      "req": "REQ-008",
      "what": "a value cannot be drawn as given (null, not finite, or outside the data contract); it is corrected or omitted",
      "todo": "Check the value against the chart's data contract (Data Model §2)"
    },
    {
      "code": "SP003",
      "severity": "warn",
      "req": "REQ-009",
      "what": "the container measures 0 px; the render is deferred",
      "todo": "Give the container a size, or pin `width` and `height`"
    },
    {
      "code": "SP004",
      "severity": "warn",
      "req": "REQ-010",
      "what": "the scale domain has zero length; it is expanded with the ground's domainPadding",
      "todo": "Nothing to do if the data is constant; otherwise check the accessor"
    },
    {
      "code": "SP005",
      "severity": "error",
      "req": "REQ-025",
      "what": "more than one element is marked with white heightening; only the first is applied",
      "todo": "Heighten a single element per chart"
    },
    {
      "code": "SP006",
      "severity": "warn",
      "req": "REQ-026",
      "what": "the inker is not registered; falling back to NullInker",
      "todo": "Register the inker or fix the ground's `inker` token"
    },
    {
      "code": "SP007",
      "severity": "warn",
      "req": "REQ-045",
      "what": "the ground is not registered; falling back to silverpoint",
      "todo": "Call registerGround() before rendering, or fix the name"
    },
    {
      "code": "SP008",
      "severity": "warn",
      "req": "REQ-096",
      "what": "the data volume is above the family's threshold",
      "todo": "Aggregate the data before charting it"
    },
    {
      "code": "SP009",
      "severity": "error",
      "req": "REQ-097",
      "what": "a scale bound cannot be derived from the data and was not supplied",
      "todo": "Pass the named property explicitly"
    },
    {
      "code": "SP010",
      "severity": "warn",
      "req": "REQ-091",
      "what": "the chord ring has more than 12 categories",
      "todo": "Group the smaller categories"
    },
    {
      "code": "SP011",
      "severity": "warn",
      "req": "NFR §7",
      "what": "the path byte budget of 40 KB is exceeded",
      "todo": "Use `hatchFill: 'tile'` or a larger hatch gap"
    },
    {
      "code": "SP012",
      "severity": "error",
      "req": "REQ-127",
      "what": "the ground does not reach the minimum contrast",
      "todo": "Recompute the palette; colours are not chosen by eye"
    },
    {
      "code": "SP013",
      "severity": "warn",
      "req": "REQ-032",
      "what": "the @silverpoint/fonts face failed to load; rendering fell back to the system stack",
      "todo": "Install @silverpoint/fonts and import its stylesheet; golden images will not match until then"
    },
    {
      "code": "SP014",
      "severity": "warn",
      "req": "REQ-204",
      "what": "a dashboard cell spans more columns than the breakpoint has; it is clamped",
      "todo": "Lower the span, or give that breakpoint more columns"
    },
    {
      "code": "SP015",
      "severity": "warn",
      "req": "REQ-205",
      "what": "the dashboard layout and its children disagree; unmatched children are placed in source order, span 1",
      "todo": "Give every child a `cell` the layout declares, once"
    },
    {
      "code": "SP016",
      "severity": "warn",
      "req": "REQ-217",
      "what": "a chart in a linked dashboard has no field named by `link.key`; it shows no linked mark",
      "todo": "Link on a field every linked chart carries, or leave this chart out of the link"
    },
    {
      "code": "SP017",
      "severity": "warn",
      "req": "REQ-324",
      "what": "a value or a range cannot be drawn as given; it is clamped, rounded to its step or defaulted",
      "todo": "Keep the value within `min`..`max` and on `step`, with `min < max` and `step > 0`"
    },
    {
      "code": "SP018",
      "severity": "warn",
      "req": "REQ-319",
      "what": "the component has no accessible name: no text content and no `label`",
      "todo": "Give it visible text, or a `label` for an icon-only control"
    },
    {
      "code": "SP019",
      "severity": "warn",
      "req": "REQ-325",
      "what": "items share a key, or have none; the first is kept and the later ones are skipped",
      "todo": "Give every item a unique, non-empty `key`"
    },
    {
      "code": "SP020",
      "severity": "warn",
      "req": "REQ-437",
      "what": "the hierarchy is invalid (a duplicate or empty `id`, a missing `parent`, a cycle, or several roots); the offending rows are dropped",
      "todo": "Give every row a unique `id` and an existing `parent`, under a single root"
    },
    {
      "code": "SP021",
      "severity": "warn",
      "req": "REQ-433",
      "what": "a statistic parameter is invalid; its default is used",
      "todo": "Keep the parameter in its documented range"
    },
    {
      "code": "SP022",
      "severity": "warn",
      "req": "REQ-434",
      "what": "a group has too few observations for its statistic; they are drawn as points",
      "todo": "Give the group more observations, or expect it drawn as points"
    },
    {
      "code": "SP023",
      "severity": "warn",
      "req": "REQ-466",
      "what": "a palette colour is below its contrast threshold against its substrate; it is drawn as given",
      "todo": "Recompute the palette with checkPalette(); colours are not chosen by eye"
    },
    {
      "code": "SP024",
      "severity": "warn",
      "req": "REQ-467",
      "what": "a palette field is unknown, or its value is not a CSS colour; the field is dropped",
      "todo": "Use the fields of PALETTE_PROPERTIES with plain CSS colour values"
    },
    {
      "code": "SP025",
      "severity": "warn",
      "req": "REQ-515",
      "what": "@knight-lab/timelinejs could not be loaded; the fallback is rendered",
      "todo": "Install the optional peer @knight-lab/timelinejs and import its stylesheet"
    }
  ],
  "recommend": [
    {
      "shape": "series",
      "intent": "trend",
      "charts": [
        {
          "slug": "line-chart",
          "score": 0.9,
          "reason": "A line is the plainest reading of a value over an ordered axis."
        },
        {
          "slug": "area-chart",
          "score": 0.8,
          "reason": "An area gives one series the weight of its magnitude."
        },
        {
          "slug": "step-chart",
          "score": 0.6,
          "reason": "Steps show a value that holds until it changes."
        },
        {
          "slug": "stream-chart",
          "score": 0.5,
          "reason": "Several value columns overlay or stack as waves."
        },
        {
          "slug": "polar-line-chart",
          "score": 0.3,
          "reason": "A cyclic axis (hours, months, degrees) closes the line around a circle."
        }
      ],
      "adjust": [
        {
          "when": "values>",
          "n": 1,
          "slug": "stream-chart",
          "delta": 0.3,
          "reason": "Several value fields read together as streams."
        },
        {
          "when": "values>",
          "n": 1,
          "slug": "area-chart",
          "delta": -0.2,
          "reason": "An area draws one series only."
        }
      ]
    },
    {
      "shape": "series",
      "intent": "change",
      "charts": [
        {
          "slug": "line-chart",
          "score": 0.8,
          "reason": "The slope between points is the change."
        },
        {
          "slug": "step-chart",
          "score": 0.75,
          "reason": "Steps mark when the value changed and by how much."
        },
        {
          "slug": "area-chart",
          "score": 0.6,
          "reason": "An area shows the change in magnitude."
        },
        {
          "slug": "bump-chart",
          "score": 0.5,
          "reason": "When the change that matters is in rank."
        }
      ]
    },
    {
      "shape": "series",
      "intent": "compare",
      "charts": [
        {
          "slug": "line-chart",
          "score": 0.8,
          "reason": "A second series draws as a dotted baseline against the first."
        },
        {
          "slug": "composed-chart",
          "score": 0.75,
          "reason": "Columns and a line share one value scale."
        },
        {
          "slug": "stream-chart",
          "score": 0.6,
          "reason": "Several series overlaid on one axis."
        },
        {
          "slug": "sparkline-rows",
          "score": 0.55,
          "reason": "One small line per series, side by side with its readout."
        },
        {
          "slug": "polar-line-chart",
          "score": 0.3,
          "reason": "Values around a cycle compared by angle."
        }
      ]
    },
    {
      "shape": "series",
      "intent": "rank",
      "charts": [
        {
          "slug": "bump-chart",
          "score": 0.9,
          "reason": "The rank of each series at each x, ranks joined across x."
        }
      ]
    },
    {
      "shape": "series",
      "intent": "kpi",
      "charts": [
        {
          "slug": "sparkline-rows",
          "score": 0.85,
          "reason": "One row per series: its name, its trend and its latest readout."
        },
        {
          "slug": "kpi-card",
          "score": 0.75,
          "reason": "One metric, its delta and its trend."
        }
      ]
    },
    {
      "shape": "series",
      "intent": "part-to-whole",
      "charts": [
        {
          "slug": "stream-chart",
          "score": 0.8,
          "reason": "Stacked waves show each part of a total over x."
        }
      ]
    },
    {
      "shape": "categories",
      "intent": "compare",
      "charts": [
        {
          "slug": "bar-chart",
          "score": 0.9,
          "reason": "Bars compare values against one common baseline."
        },
        {
          "slug": "lollipop-chart",
          "score": 0.75,
          "reason": "A lighter mark per category, readable with many of them."
        },
        {
          "slug": "radar-chart",
          "score": 0.5,
          "reason": "Spokes compare a few subjects at once."
        },
        {
          "slug": "polar-bar-chart",
          "score": 0.4,
          "reason": "Bars around a circle, for a cyclic set of categories."
        },
        {
          "slug": "coxcomb-chart",
          "score": 0.35,
          "reason": "Equal angles, area by value: cyclic categories such as months."
        },
        {
          "slug": "radial-arc-group",
          "score": 0.3,
          "reason": "Concentric tracks, each swept by its value."
        }
      ],
      "adjust": [
        {
          "when": "rows>",
          "n": 12,
          "slug": "lollipop-chart",
          "delta": 0.2,
          "reason": "Many categories read better as lollipops."
        },
        {
          "when": "rows>",
          "n": 12,
          "slug": "radar-chart",
          "delta": -0.3,
          "reason": "Radial layouts crowd past a dozen categories."
        },
        {
          "when": "rows>",
          "n": 12,
          "slug": "polar-bar-chart",
          "delta": -0.3,
          "reason": "Radial layouts crowd past a dozen categories."
        },
        {
          "when": "rows>",
          "n": 12,
          "slug": "coxcomb-chart",
          "delta": -0.3,
          "reason": "Radial layouts crowd past a dozen categories."
        },
        {
          "when": "values>",
          "n": 1,
          "slug": "bar-chart",
          "delta": 0.05,
          "reason": "A second value field draws as a second series of bars."
        }
      ]
    },
    {
      "shape": "categories",
      "intent": "rank",
      "charts": [
        {
          "slug": "bar-chart",
          "score": 0.85,
          "reason": "Sorted bars read as a ranking."
        },
        {
          "slug": "lollipop-chart",
          "score": 0.85,
          "reason": "Lollipops sort themselves with `sort`."
        },
        {
          "slug": "pyramid-chart",
          "score": 0.5,
          "reason": "Stacked tiers, widest at the base."
        },
        {
          "slug": "polar-bar-chart",
          "score": 0.4,
          "reason": "A ranking around a circle."
        }
      ]
    },
    {
      "shape": "categories",
      "intent": "part-to-whole",
      "charts": [
        {
          "slug": "stacked-bar-chart",
          "score": 0.85,
          "reason": "Each bar stacks its parts, one segment per value column."
        },
        {
          "slug": "waterfall-chart",
          "score": 0.6,
          "reason": "Parts that add up to a running total."
        },
        {
          "slug": "coxcomb-chart",
          "score": 0.4,
          "reason": "Sectors whose area is each part."
        }
      ]
    },
    {
      "shape": "categories",
      "intent": "change",
      "charts": [
        {
          "slug": "dumbbell-chart",
          "score": 0.9,
          "reason": "Two values per category joined by a segment: before and after."
        },
        {
          "slug": "slope-chart",
          "score": 0.85,
          "reason": "Two period axes, one segment per category: the slope is the change."
        },
        {
          "slug": "waterfall-chart",
          "score": 0.75,
          "reason": "Each step a delta from the running total."
        }
      ]
    },
    {
      "shape": "categories",
      "intent": "progress",
      "charts": [
        {
          "slug": "bullet-chart",
          "score": 0.9,
          "reason": "Each bar against its own target."
        },
        {
          "slug": "radial-rings",
          "score": 0.75,
          "reason": "Concentric rings, each swept to its percent."
        },
        {
          "slug": "funnel-chart",
          "score": 0.7,
          "reason": "Stages that narrow, such as a conversion."
        },
        {
          "slug": "radial-arc-group",
          "score": 0.5,
          "reason": "Tracks swept relative to the largest."
        }
      ]
    },
    {
      "shape": "categories",
      "intent": "kpi",
      "charts": [
        {
          "slug": "bullet-chart",
          "score": 0.8,
          "reason": "Each measure against its target, compact."
        },
        {
          "slug": "radial-rings",
          "score": 0.6,
          "reason": "A few percents at a glance."
        }
      ]
    },
    {
      "shape": "parts",
      "intent": "part-to-whole",
      "charts": [
        {
          "slug": "donut-chart",
          "score": 0.9,
          "reason": "A ring reads a few shares of one whole around a central figure."
        },
        {
          "slug": "waffle-chart",
          "score": 0.85,
          "reason": "Unit cells make the shares countable."
        },
        {
          "slug": "treemap-chart",
          "score": 0.7,
          "reason": "Tiles sized by share."
        },
        {
          "slug": "diverging-bar-chart",
          "score": 0.4,
          "reason": "For ordered levels (agree… disagree) around a neutral centre."
        },
        {
          "slug": "stacked-bar-chart",
          "score": 0.35,
          "reason": "One bar stacked with the shares, to set beside other wholes."
        }
      ],
      "adjust": [
        {
          "when": "rows>",
          "n": 6,
          "slug": "donut-chart",
          "delta": -0.3,
          "reason": "A ring loses its shares past six slices."
        },
        {
          "when": "rows>",
          "n": 6,
          "slug": "treemap-chart",
          "delta": 0.1,
          "reason": "Tiles hold many shares better than a ring."
        }
      ]
    },
    {
      "shape": "parts",
      "intent": "compare",
      "charts": [
        {
          "slug": "diverging-bar-chart",
          "score": 0.8,
          "reason": "Likert-style levels on both sides of a neutral centre, row by row."
        },
        {
          "slug": "waffle-chart",
          "score": 0.6,
          "reason": "Countable cells per part."
        }
      ]
    },
    {
      "shape": "parts",
      "intent": "progress",
      "charts": [
        {
          "slug": "waffle-chart",
          "score": 0.8,
          "reason": "A hundred cells filled to the share done."
        }
      ]
    },
    {
      "shape": "matrix",
      "intent": "compare",
      "charts": [
        {
          "slug": "heatmap-chart",
          "score": 0.9,
          "reason": "One toned cell per row and column."
        },
        {
          "slug": "marimekko-chart",
          "score": 0.7,
          "reason": "Columns by total, segments by share."
        },
        {
          "slug": "parallel-coordinates-chart",
          "score": 0.6,
          "reason": "One polyline per row across many dimensions."
        }
      ]
    },
    {
      "shape": "matrix",
      "intent": "part-to-whole",
      "charts": [
        {
          "slug": "marimekko-chart",
          "score": 0.9,
          "reason": "Each column a whole, each segment its share, column width by total."
        }
      ]
    },
    {
      "shape": "matrix",
      "intent": "correlation",
      "charts": [
        {
          "slug": "parallel-coordinates-chart",
          "score": 0.9,
          "reason": "Crossing lines between axes show how dimensions move together."
        },
        {
          "slug": "heatmap-chart",
          "score": 0.6,
          "reason": "A grid of values, read for patterns."
        }
      ]
    },
    {
      "shape": "matrix",
      "intent": "distribution",
      "charts": [
        {
          "slug": "heatmap-chart",
          "score": 0.8,
          "reason": "Where the high values gather in the grid."
        }
      ]
    },
    {
      "shape": "hierarchy",
      "intent": "hierarchy",
      "charts": [
        {
          "slug": "tree-chart",
          "score": 0.85,
          "reason": "The structure itself, node by node."
        },
        {
          "slug": "squarified-treemap",
          "score": 0.8,
          "reason": "Nested rectangles, drillable."
        },
        {
          "slug": "sunburst-chart",
          "score": 0.75,
          "reason": "Rings of arcs, one ring per level, drillable."
        }
      ]
    },
    {
      "shape": "hierarchy",
      "intent": "part-to-whole",
      "charts": [
        {
          "slug": "squarified-treemap",
          "score": 0.9,
          "reason": "Area by value, nested by level."
        },
        {
          "slug": "sunburst-chart",
          "score": 0.85,
          "reason": "Each arc its share of its parent."
        }
      ]
    },
    {
      "shape": "links",
      "intent": "flow",
      "charts": [
        {
          "slug": "sankey-chart",
          "score": 0.9,
          "reason": "Bands between layered stages, width by value."
        },
        {
          "slug": "chord-ring",
          "score": 0.75,
          "reason": "Flows between categories around a circle, both ways."
        },
        {
          "slug": "network-chart",
          "score": 0.5,
          "reason": "When the links matter more than their volume."
        }
      ]
    },
    {
      "shape": "links",
      "intent": "network",
      "charts": [
        {
          "slug": "network-chart",
          "score": 0.9,
          "reason": "Nodes and links laid out by a seeded force."
        },
        {
          "slug": "chord-ring",
          "score": 0.7,
          "reason": "Who connects to whom, around a circle."
        }
      ]
    },
    {
      "shape": "links",
      "intent": "part-to-whole",
      "charts": [
        {
          "slug": "sankey-chart",
          "score": 0.8,
          "reason": "How a total splits and merges across stages."
        }
      ]
    },
    {
      "shape": "points",
      "intent": "correlation",
      "charts": [
        {
          "slug": "scatter-chart",
          "score": 0.9,
          "reason": "Points on two linear scales."
        },
        {
          "slug": "bubble-chart",
          "score": 0.75,
          "reason": "A third variable as each point’s area."
        },
        {
          "slug": "density-bin-chart",
          "score": 0.6,
          "reason": "Counts per bin when points overlap."
        },
        {
          "slug": "connected-scatter-chart",
          "score": 0.5,
          "reason": "When the points have an order."
        },
        {
          "slug": "polar-scatter-chart",
          "score": 0.3,
          "reason": "When one variable is an angle."
        }
      ],
      "adjust": [
        {
          "when": "rows>",
          "n": 500,
          "slug": "density-bin-chart",
          "delta": 0.35,
          "reason": "Hundreds of points read better as counts per bin."
        },
        {
          "when": "rows>",
          "n": 500,
          "slug": "scatter-chart",
          "delta": -0.2,
          "reason": "Points overplot and hide their density."
        },
        {
          "when": "values>",
          "n": 2,
          "slug": "bubble-chart",
          "delta": 0.2,
          "reason": "A third numeric field can size the points."
        }
      ]
    },
    {
      "shape": "points",
      "intent": "distribution",
      "charts": [
        {
          "slug": "density-bin-chart",
          "score": 0.85,
          "reason": "Points counted in hexagonal or square bins."
        },
        {
          "slug": "contour-chart",
          "score": 0.8,
          "reason": "Iso-lines of the density."
        },
        {
          "slug": "scatter-chart",
          "score": 0.6,
          "reason": "Every point, when there are few."
        },
        {
          "slug": "polar-scatter-chart",
          "score": 0.4,
          "reason": "Points by angle and radius."
        }
      ]
    },
    {
      "shape": "points",
      "intent": "change",
      "charts": [
        {
          "slug": "connected-scatter-chart",
          "score": 0.9,
          "reason": "An ordered path through x-y points: how two values moved together."
        }
      ]
    },
    {
      "shape": "points",
      "intent": "network",
      "charts": [
        {
          "slug": "delaunay-chart",
          "score": 0.85,
          "reason": "Neighbours by triangulation, or each point’s Voronoi cell."
        }
      ]
    },
    {
      "shape": "points",
      "intent": "compare",
      "charts": [
        {
          "slug": "bubble-chart",
          "score": 0.7,
          "reason": "Positions and sizes compared at once."
        }
      ]
    },
    {
      "shape": "distribution",
      "intent": "distribution",
      "charts": [
        {
          "slug": "histogram-chart",
          "score": 0.9,
          "reason": "Observations binned in the core."
        },
        {
          "slug": "box-plot-chart",
          "score": 0.8,
          "reason": "Quartiles, median, whiskers and outliers."
        },
        {
          "slug": "violin-chart",
          "score": 0.75,
          "reason": "The density’s shape, mirrored."
        },
        {
          "slug": "beeswarm-chart",
          "score": 0.7,
          "reason": "Every observation, packed without overlap."
        },
        {
          "slug": "ecdf-chart",
          "score": 0.65,
          "reason": "The cumulative share below each value."
        },
        {
          "slug": "wind-rose",
          "score": 0.3,
          "reason": "When the observations carry a bearing."
        }
      ],
      "adjust": [
        {
          "when": "rows<",
          "n": 30,
          "slug": "beeswarm-chart",
          "delta": 0.25,
          "reason": "Few observations: show each one."
        },
        {
          "when": "rows<",
          "n": 30,
          "slug": "histogram-chart",
          "delta": -0.2,
          "reason": "Few observations make coarse bins."
        },
        {
          "when": "rows>",
          "n": 1000,
          "slug": "beeswarm-chart",
          "delta": -0.4,
          "reason": "Too many observations to draw one by one."
        }
      ]
    },
    {
      "shape": "distribution",
      "intent": "compare",
      "charts": [
        {
          "slug": "box-plot-chart",
          "score": 0.9,
          "reason": "Quartiles side by side, one box per group."
        },
        {
          "slug": "violin-chart",
          "score": 0.85,
          "reason": "Density shapes side by side."
        },
        {
          "slug": "ridgeline-chart",
          "score": 0.8,
          "reason": "Densities on overlapping baselines, one per group."
        },
        {
          "slug": "ecdf-chart",
          "score": 0.75,
          "reason": "Cumulative curves of each group on one axis."
        }
      ]
    },
    {
      "shape": "distribution",
      "intent": "change",
      "charts": [
        {
          "slug": "ridgeline-chart",
          "score": 0.85,
          "reason": "A density per period, stacked in order."
        }
      ]
    },
    {
      "shape": "intervals",
      "intent": "uncertainty",
      "charts": [
        {
          "slug": "error-bar-chart",
          "score": 0.9,
          "reason": "A point estimate with its interval per category."
        },
        {
          "slug": "range-band-chart",
          "score": 0.85,
          "reason": "A band between low and high over x."
        }
      ]
    },
    {
      "shape": "intervals",
      "intent": "trend",
      "charts": [
        {
          "slug": "range-band-chart",
          "score": 0.85,
          "reason": "The band between low and high over time."
        },
        {
          "slug": "candlestick-chart",
          "score": 0.8,
          "reason": "Open, high, low and close per period."
        }
      ]
    },
    {
      "shape": "intervals",
      "intent": "change",
      "charts": [
        {
          "slug": "candlestick-chart",
          "score": 0.9,
          "reason": "Each period’s open-to-close change and its range."
        }
      ]
    },
    {
      "shape": "intervals",
      "intent": "schedule",
      "charts": [
        {
          "slug": "interval-chart",
          "score": 0.95,
          "reason": "Floating bars from start to end on lanes."
        }
      ]
    },
    {
      "shape": "events",
      "intent": "schedule",
      "charts": [
        {
          "slug": "activity-grid",
          "score": 0.85,
          "reason": "One cell per day, a column per week."
        }
      ]
    },
    {
      "shape": "events",
      "intent": "trend",
      "charts": [
        {
          "slug": "activity-grid",
          "score": 0.8,
          "reason": "Activity per day over weeks."
        }
      ]
    },
    {
      "shape": "single",
      "intent": "kpi",
      "charts": [
        {
          "slug": "kpi-card",
          "score": 0.9,
          "reason": "The figure, its delta and its trend."
        },
        {
          "slug": "gauge-arc",
          "score": 0.75,
          "reason": "A percent on a 240° arc."
        },
        {
          "slug": "meter-chart",
          "score": 0.7,
          "reason": "A percent with a needle."
        }
      ]
    },
    {
      "shape": "single",
      "intent": "progress",
      "charts": [
        {
          "slug": "gauge-arc",
          "score": 0.85,
          "reason": "An arc swept to the percent done."
        },
        {
          "slug": "meter-chart",
          "score": 0.8,
          "reason": "A needle at the percent done."
        }
      ]
    },
    {
      "shape": "field",
      "intent": "flow",
      "charts": [
        {
          "slug": "vector-field-chart",
          "score": 0.95,
          "reason": "An arrow per grid point, its direction and magnitude."
        }
      ]
    },
    {
      "shape": "field",
      "intent": "distribution",
      "charts": [
        {
          "slug": "contour-chart",
          "score": 0.85,
          "reason": "Iso-lines and bands of a scalar grid (`source: 'grid'`)."
        }
      ]
    }
  ],
  "stylesheets": {
    "always": [
      "@silverpoint/fonts/fonts.css",
      "@silverpoint/grounds/styles.css"
    ],
    "ui": [
      "@silverpoint/grounds/ui.css"
    ],
    "timeline": [
      "@knight-lab/timelinejs/dist/css/timeline.css",
      "@silverpoint/grounds/timeline.css"
    ]
  }
}
