{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://syntariui.github.io/syntari/registry/schema/component.schema.json",
  "title": "SyntariComponent",
  "description": "Machine-readable contract for one Syntari component or agent pattern.",
  "type": "object",
  "required": [
    "id",
    "name",
    "version",
    "category",
    "purpose",
    "variants",
    "states",
    "anatomy",
    "accessibility",
    "tokens"
  ],
  "properties": {
    "id": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
    "name": { "type": "string" },
    "version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
    "category": { "type": "string" },
    "purpose": { "type": "string" },
    "description": { "type": "string" },
    "intents": { "type": "array", "items": { "type": "string" } },
    "variants": {
      "type": "object",
      "additionalProperties": { "type": "array", "items": { "type": "string" } }
    },
    "states": { "type": "array", "items": { "type": "string" } },
    "anatomy": { "type": "array", "items": { "type": "string" } },
    "accessibility": {
      "type": "object",
      "required": ["role", "keyboard", "accessibleNameRequired"],
      "properties": {
        "role": { "type": "string" },
        "keyboard": { "type": "array", "items": { "type": "string" } },
        "accessibleNameRequired": { "type": "boolean" },
        "liveRegion": { "type": "string" },
        "focusTrap": { "type": "boolean" },
        "focusRestoration": { "type": "boolean" }
      }
    },
    "rules": { "type": "array", "items": { "type": "string" } },
    "tokens": { "type": "array", "items": { "type": "string" } },
    "props": {
      "type": "object",
      "description": "Prop contract an agent may set through the Syntari UI IR. Absent means the component is documented but not yet renderable from IR.",
      "additionalProperties": { "$ref": "#/definitions/prop" }
    },
    "ir": {
      "type": "object",
      "description": "Maps validated props onto the component's own markup. The renderer mounts the component, keeps the node this declares, then writes prop values into the declared slots.",
      "properties": {
        "node": { "type": "string", "description": "Instance root inside the mounted component. Everything else in the mounted element is discarded." },
        "text": { "$ref": "#/definitions/selectorMap" },
        "lead": { "$ref": "#/definitions/selectorMap" },
        "icon": { "$ref": "#/definitions/selectorMap" },
        "variant": { "type": "object", "additionalProperties": { "$ref": "#/definitions/variantBinding" } },
        "class": { "type": "object", "description": "Prop name to class name. A truthy value adds the class, a false value removes it.", "additionalProperties": { "type": "string" } },
        "series": { "type": "object", "description": "Numeric series drawn as SVG paths, so a chart is data rather than markup.", "additionalProperties": { "$ref": "#/definitions/seriesBinding" } },
        "attributes": { "type": "object", "additionalProperties": { "$ref": "#/definitions/attributeBinding" } },
        "list": { "type": "object", "additionalProperties": { "oneOf": [ { "$ref": "#/definitions/listPart" }, { "type": "array", "items": { "$ref": "#/definitions/listPart" } } ] } }
      },
      "additionalProperties": false
    },
    "compatibleWith": { "type": "array", "items": { "type": "string" } },
    "avoidWhen": { "type": "array", "items": { "type": "string" } },
    "dependencies": { "type": "array", "items": { "type": "string" } },
    "agentEvents": { "type": "array", "items": { "type": "string" } },
    "composition": {
      "type": "object",
      "properties": {
        "requires": { "type": "array", "items": { "type": "string" } },
        "mayContain": { "type": "array", "items": { "type": "string" } },
        "forbidden": { "type": "array", "items": { "type": "string" } },
        "actions": {
          "type": "object",
          "properties": {
            "primaryMax": { "type": "integer" },
            "destructiveRequiresConfirmation": { "type": "boolean" }
          }
        }
      }
    },
    "semantics": {
      "type": "object",
      "properties": {
        "intent": { "type": "array", "items": { "type": "string" } },
        "density": { "type": "array", "items": { "type": "string" } },
        "attention": { "type": "string" },
        "risk": { "type": "string" },
        "interaction": { "type": "string" },
        "context": { "type": "array", "items": { "type": "string" } },
        "action": { "type": "array", "items": { "type": "string" } },
        "reversibility": { "type": "string" },
        "ownership": { "type": "string" }
      }
    },
    "examples": {
      "type": "object",
      "properties": {
        "good": { "type": "array", "items": { "type": "string" } },
        "bad": { "type": "array", "items": { "type": "string" } },
        "boundary": { "type": "array", "items": { "type": "string" } }
      }
    },
    "source": { "type": "string" },
    "status": { "enum": ["authored", "generated", "draft"] }
  },
  "definitions": {
    "prop": {
      "type": "object",
      "required": ["type"],
      "properties": {
        "type": { "enum": ["string", "number", "boolean", "enum", "array", "object"] },
        "required": { "type": "boolean" },
        "description": { "type": "string" },
        "maxLength": { "type": "integer", "minimum": 1 },
        "minimum": { "type": "number" },
        "maximum": { "type": "number" },
        "values": { "type": "array" },
        "default": {},
        "maxItems": { "type": "integer", "minimum": 1 },
        "items": { "$ref": "#/definitions/prop" },
        "fields": { "type": "object", "additionalProperties": { "$ref": "#/definitions/prop" } }
      },
      "additionalProperties": false
    },
    "selectorMap": {
      "type": "object",
      "description": "Prop name to CSS selector, resolved inside the instance root or the list item.",
      "additionalProperties": { "type": "string" }
    },
    "variantBinding": {
      "type": "object",
      "required": ["values"],
      "properties": {
        "selector": { "type": "string" },
        "values": { "type": "object", "additionalProperties": { "type": "string" } }
      },
      "additionalProperties": false
    },
    "styleBinding": {
      "type": "object",
      "required": ["name"],
      "properties": {
        "name": { "type": "string" },
        "suffix": { "type": "string" }
      },
      "additionalProperties": false
    },
    "attributeBinding": {
      "type": "object",
      "required": ["selector", "attribute"],
      "properties": {
        "selector": { "type": "string" },
        "attribute": { "type": "string" }
      },
      "additionalProperties": false
    },
    "seriesBinding": {
      "type": "object",
      "required": ["selector", "line"],
      "properties": {
        "selector": { "type": "string", "description": "The SVG that owns the geometry." },
        "line": { "type": "string", "description": "Path that receives the stroked line." },
        "fill": { "type": "string", "description": "Path that receives the same series closed to the baseline." },
        "viewBox": { "type": "string" },
        "value": { "type": "string", "description": "Field of each point that carries the number. Defaults to value." },
        "inset": {
          "type": "object",
          "properties": { "top": { "type": "number" }, "bottom": { "type": "number" }, "left": { "type": "number" }, "right": { "type": "number" } }
        },
        "scale": {
          "type": "object",
          "properties": { "min": { "type": "number" }, "max": { "type": "number" } }
        }
      },
      "additionalProperties": false
    },
    "listPart": {
      "type": "object",
      "required": ["container", "item"],
      "properties": {
        "container": { "type": "string" },
        "item": { "type": "string", "description": "Template node. The first match is cloned for every item and the demo copies are removed." },
        "text": { "$ref": "#/definitions/selectorMap" },
        "lead": { "$ref": "#/definitions/selectorMap" },
        "icon": { "$ref": "#/definitions/selectorMap" },
        "variant": { "type": "object", "additionalProperties": { "$ref": "#/definitions/variantBinding" } },
        "class": { "type": "object", "additionalProperties": { "type": "string" } },
        "attributes": { "type": "object", "additionalProperties": { "$ref": "#/definitions/attributeBinding" } },
        "style": { "type": "object", "additionalProperties": { "$ref": "#/definitions/styleBinding" } },
        "strip": { "type": "array", "items": { "type": "string" }, "description": "Demo-only attributes removed from generated items." }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": true
}
