{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/iyulab/u-widgets/schema/u-widget.schema.json",
  "title": "u-widget",
  "description": "Declarative, data-driven widget specification for u-widgets v0.4",
  "oneOf": [
    { "$ref": "#/$defs/widget" },
    { "$ref": "#/$defs/composeWidget" }
  ],
  "$defs": {
    "widgetType": {
      "type": "string",
      "enum": [
        "metric", "stat-group", "gauge", "progress",
        "table", "list",
        "chart.bar", "chart.line", "chart.area", "chart.pie",
        "chart.scatter", "chart.radar", "chart.heatmap", "chart.box",
        "chart.funnel", "chart.waterfall", "chart.treemap", "chart.histogram",
        "form", "confirm",
        "markdown", "image", "callout",
        "kv", "code", "citation", "status", "steps",
        "rating", "video", "gallery", "math",
        "actions", "divider", "header"
      ],
      "description": "Widget type identifier"
    },
    "widget": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "const": "u-widget"
        },
        "version": {
          "type": "string"
        },
        "widget": {
          "$ref": "#/$defs/widgetType"
        },
        "id": {
          "type": "string",
          "description": "Optional unique identifier for the widget"
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "data": {
          "oneOf": [
            { "type": "object" },
            { "type": "array", "items": { "type": "object" } }
          ],
          "description": "Inline data (object or array of objects)"
        },
        "mapping": {
          "$ref": "#/$defs/mapping"
        },
        "fields": {
          "type": "array",
          "items": { "$ref": "#/$defs/fieldDefinition" },
          "description": "Form/confirm field definitions (input widgets only)"
        },
        "formdown": {
          "type": "string",
          "description": "Form/confirm field definitions in formdown syntax. Mutually exclusive with fields."
        },
        "options": {
          "type": "object",
          "description": "Widget-specific rendering options"
        },
        "actions": {
          "type": "array",
          "items": { "$ref": "#/$defs/action" }
        }
      },
      "required": ["widget"],
      "additionalProperties": false
    },
    "composeWidget": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "const": "u-widget"
        },
        "version": {
          "type": "string"
        },
        "widget": {
          "type": "string",
          "const": "compose"
        },
        "id": {
          "type": "string",
          "description": "Optional unique identifier for the widget"
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "layout": {
          "type": "string",
          "enum": ["stack", "row", "grid"],
          "default": "stack",
          "description": "Layout mode for children"
        },
        "columns": {
          "type": "integer",
          "minimum": 1,
          "default": 2,
          "description": "Number of columns for grid layout"
        },
        "children": {
          "type": "array",
          "items": { "$ref": "#/$defs/childWidget" }
        },
        "options": {
          "type": "object"
        },
        "actions": {
          "type": "array",
          "items": { "$ref": "#/$defs/action" }
        }
      },
      "required": ["widget", "children"],
      "additionalProperties": false
    },
    "childWidget": {
      "type": "object",
      "properties": {
        "widget": {
          "type": "string",
          "description": "Widget type (inherits type/version from parent)"
        },
        "id": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "span": {
          "type": "integer",
          "minimum": 1,
          "description": "Grid span width"
        },
        "collapsed": {
          "type": "boolean",
          "default": false,
          "description": "Whether the child widget is initially collapsed (rendered in a details/summary element)"
        },
        "data": {
          "oneOf": [
            { "type": "object" },
            { "type": "array", "items": { "type": "object" } }
          ]
        },
        "mapping": {
          "$ref": "#/$defs/mapping"
        },
        "fields": {
          "type": "array",
          "items": { "$ref": "#/$defs/fieldDefinition" }
        },
        "formdown": {
          "type": "string",
          "description": "Form/confirm field definitions in formdown syntax"
        },
        "options": {
          "type": "object"
        },
        "actions": {
          "type": "array",
          "items": { "$ref": "#/$defs/action" }
        }
      },
      "required": ["widget"],
      "additionalProperties": false
    },
    "mapping": {
      "type": "object",
      "description": "Data field to visual channel mapping",
      "properties": {
        "x": {
          "type": "string",
          "description": "X-axis field"
        },
        "y": {
          "oneOf": [
            { "type": "string" },
            { "type": "array", "items": { "type": "string" } }
          ],
          "description": "Y-axis field(s). Single string is normalized to array internally."
        },
        "label": {
          "type": "string",
          "description": "Label field (pie charts etc.)"
        },
        "value": {
          "type": "string",
          "description": "Value field (pie charts etc.)"
        },
        "color": {
          "type": "string",
          "description": "Color grouping field"
        },
        "size": {
          "type": "string",
          "description": "Size encoding field (scatter)"
        },
        "opacity": {
          "type": "string",
          "description": "Opacity encoding field (scatter, maps values to 0.1-1.0)"
        },
        "axis": {
          "type": "string",
          "description": "Axis field (radar)"
        },
        "columns": {
          "type": "array",
          "items": { "$ref": "#/$defs/columnDefinition" },
          "description": "Table column definitions"
        },
        "primary": {
          "type": "string",
          "description": "Primary text field (list)"
        },
        "secondary": {
          "type": "string",
          "description": "Secondary text field (list)"
        },
        "icon": {
          "type": "string",
          "description": "Icon field (list)"
        },
        "avatar": {
          "type": "string",
          "description": "Avatar image URL field (list)"
        },
        "trailing": {
          "type": "string",
          "description": "Trailing text field (list)"
        },
        "badge": {
          "type": "string",
          "description": "Badge/tag field (list)"
        }
      },
      "additionalProperties": false
    },
    "columnDefinition": {
      "type": "object",
      "properties": {
        "field": {
          "type": "string",
          "description": "Data key"
        },
        "label": {
          "type": "string",
          "description": "Column header (defaults to field name)"
        },
        "format": {
          "type": "string",
          "enum": ["number", "currency", "percent", "date", "datetime", "bytes"],
          "description": "Format hint"
        },
        "align": {
          "type": "string",
          "enum": ["left", "center", "right"],
          "description": "Column alignment"
        }
      },
      "required": ["field"],
      "additionalProperties": false
    },
    "fieldDefinition": {
      "type": "object",
      "properties": {
        "field": {
          "type": "string",
          "description": "Key name in submitted data"
        },
        "label": {
          "type": "string",
          "description": "Display label"
        },
        "type": {
          "type": "string",
          "enum": [
            "text", "email", "password", "tel", "url",
            "textarea", "number", "select", "multiselect",
            "date", "datetime", "time",
            "toggle", "range", "radio", "checkbox"
          ],
          "description": "Input type"
        },
        "required": {
          "type": "boolean"
        },
        "placeholder": {
          "type": "string"
        },
        "options": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Choices for select/multiselect/radio/checkbox"
        },
        "minLength": {
          "type": "integer",
          "description": "Minimum character length for text inputs"
        },
        "maxLength": {
          "type": "integer"
        },
        "pattern": {
          "type": "string",
          "description": "Custom regex pattern for validation"
        },
        "rows": {
          "type": "integer",
          "description": "Number of rows for textarea"
        },
        "min": {
          "description": "Minimum value (number or date string)"
        },
        "max": {
          "description": "Maximum value (number or date string)"
        },
        "step": {
          "type": "number"
        },
        "message": {
          "type": "string",
          "description": "Custom validation error message (overrides locale default)"
        }
      },
      "required": ["field"],
      "additionalProperties": false
    },
    "action": {
      "type": "object",
      "properties": {
        "label": {
          "type": "string",
          "description": "Button text"
        },
        "action": {
          "type": "string",
          "description": "Action identifier (submit, cancel, navigate, or custom)"
        },
        "style": {
          "type": "string",
          "enum": ["primary", "danger", "default"],
          "default": "default"
        },
        "disabled": {
          "type": "boolean",
          "default": false
        },
        "url": {
          "type": "string",
          "description": "URL for navigate action"
        }
      },
      "required": ["label", "action"],
      "additionalProperties": false
    }
  }
}
