{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://microcharts.dev/catalog.schema.json",
  "title": "microcharts catalog",
  "description": "Machine-readable catalog of every microcharts chart: import paths, data shape, primary encoding, and props. Full API for a chart = sharedProps + charts[n].props; interactive shared callbacks apply only when listed in charts[n].sharedInteractive. See top-level howToRead. Generated from the chart registry; served at /catalog.json.",
  "type": "object",
  "additionalProperties": false,
  "required": ["package", "homepage", "howToRead", "mcp", "sharedProps", "charts"],
  "properties": {
    "$schema": {
      "type": "string",
      "format": "uri",
      "description": "URI of this schema."
    },
    "package": {
      "type": "string",
      "description": "npm package name to install.",
      "examples": ["@microcharts/react"]
    },
    "homepage": {
      "type": "string",
      "format": "uri",
      "description": "Documentation site origin."
    },
    "howToRead": {
      "type": "string",
      "minLength": 1,
      "description": "Instructions for assembling a chart's full prop surface from sharedProps, props, and sharedInteractive."
    },
    "mcp": {
      "type": "object",
      "additionalProperties": false,
      "required": ["package", "command", "transport", "docs", "tools"],
      "description": "The same catalog exposed as a Model Context Protocol server: an agent that can spawn one should prefer calling it over re-reading this file.",
      "properties": {
        "package": {
          "type": "string",
          "description": "npm package providing the MCP server.",
          "examples": ["@microcharts/mcp"]
        },
        "command": {
          "type": "string",
          "description": "Command an MCP client runs to start the server over stdio."
        },
        "transport": {
          "const": "stdio",
          "description": "Transport the server speaks."
        },
        "docs": {
          "type": "string",
          "format": "uri",
          "description": "Human documentation for the server."
        },
        "tools": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string"
          },
          "description": "Tool names the server registers."
        }
      }
    },
    "sharedProps": {
      "type": "array",
      "description": "Props whose name means the same thing wherever they appear — grammar, layout, i18n, and shared interactive props. Interactive names in this list apply to a chart ONLY when also listed in that chart's sharedInteractive.",
      "items": {
        "$ref": "#/$defs/prop"
      }
    },
    "charts": {
      "type": "array",
      "description": "Every catalogued chart.",
      "items": {
        "$ref": "#/$defs/chart"
      }
    }
  },
  "$defs": {
    "prop": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "type", "required", "description"],
      "properties": {
        "name": {
          "type": "string",
          "description": "Prop name as written in JSX. A `/` joins a documented pair (e.g. `xLabel / yLabel`)."
        },
        "type": {
          "type": "string",
          "description": "TypeScript type, as source text."
        },
        "required": {
          "type": "boolean",
          "description": "Whether the prop must be passed."
        },
        "description": {
          "type": "string",
          "minLength": 1,
          "description": "One-line human description of the prop."
        },
        "interactive": {
          "const": true,
          "description": "Present and `true` only when the prop exists on the `…/interactive` entry alone (the static default component does not accept it)."
        }
      }
    },
    "chart": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "name",
        "slug",
        "status",
        "collection",
        "tagline",
        "docs",
        "staticImport",
        "dataShape",
        "primaryEncoding",
        "precision",
        "nodeBudget",
        "bestFor",
        "avoidFor",
        "props",
        "examples"
      ],
      "properties": {
        "name": {
          "type": "string",
          "description": "Component name (PascalCase).",
          "examples": ["Sparkline"]
        },
        "slug": {
          "type": "string",
          "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
          "description": "URL/registry slug (kebab-case)."
        },
        "status": {
          "enum": ["stable", "planned"],
          "description": "`stable` ships today; `planned` is catalogued but not yet released."
        },
        "collection": {
          "enum": ["core", "decision", "expressive", "frontier"],
          "description": "Catalog collection — metadata for browsing, never an import-path boundary."
        },
        "tagline": {
          "type": "string",
          "minLength": 1,
          "description": "One line: the decision this chart answers."
        },
        "docs": {
          "type": "string",
          "format": "uri",
          "description": "Absolute URL of the chart's documentation page."
        },
        "staticImport": {
          "type": "string",
          "description": "Import path of the static, RSC-safe default entry.",
          "examples": ["@microcharts/react/sparkline"]
        },
        "interactiveImport": {
          "type": "string",
          "description": "Import path of the `…/interactive` client entry, when the chart has one.",
          "examples": ["@microcharts/react/sparkline/interactive"]
        },
        "picker": {
          "type": "boolean",
          "description": "Present on interactive charts. `true` ⇒ multi-unit picker contract (onActive / onSelect / selectedIndex / defaultSelectedIndex). `false` ⇒ no roving picker (lean scalars, MinimapStrip, TokenConfidence)."
        },
        "animates": {
          "type": "boolean",
          "description": "Present on interactive charts. `true` ⇒ accepts shared `animate` (requires `@microcharts/react/motion`). `false` ⇒ no entrance motion prop."
        },
        "sharedInteractive": {
          "type": "array",
          "description": "Exact shared interactive prop names this chart's `/interactive` entry accepts (subset of sharedProps). Empty array ⇒ interactive entry exists but takes none of the shared interactive props. Omit the field when there is no interactive entry.",
          "items": {
            "type": "string",
            "enum": [
              "animate",
              "live",
              "onActive",
              "onSelect",
              "selectedIndex",
              "defaultSelectedIndex",
              "readout"
            ]
          }
        },
        "dataShape": {
          "type": "string",
          "description": "The shape of the `data` prop, as source text."
        },
        "primaryEncoding": {
          "type": "string",
          "description": "The one documented primary encoding channel."
        },
        "precision": {
          "type": "string",
          "minLength": 1,
          "description": "How precisely that channel can be read — `high`, `medium`, `low`, often with the chart to steer to when an exact read matters."
        },
        "nodeBudget": {
          "type": "string",
          "minLength": 1,
          "description": "SVG nodes a typical render emits, e.g. `≤ 6` or `1 per cell`."
        },
        "bestFor": {
          "type": "array",
          "description": "Situations this chart is the right pick for.",
          "items": {
            "type": "string"
          }
        },
        "avoidFor": {
          "type": "array",
          "description": "Situations to reach for a different chart instead.",
          "items": {
            "type": "string"
          }
        },
        "props": {
          "type": "array",
          "description": "Chart-specific props only. Combine with sharedProps; apply shared interactive names only when listed in sharedInteractive. Chart-specific callbacks (e.g. onWindowChange) appear here with interactive:true.",
          "items": {
            "$ref": "#/$defs/prop"
          }
        },
        "examples": {
          "type": "array",
          "description": "Runnable usage examples.",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["title", "code"],
            "properties": {
              "title": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
