ngx-json-render UI
Renders dashboards, forms and tables inline in the chat as Angular Material components (MCP App).
¿Debería usar esto?
Calidad y seguridad
Hallazgos (1)
- LOWen render-ui
Basado en el análisis automatizado de las definiciones de herramientas y el cumplimiento del protocolo.
Costo de contexto
Este es el número aproximado de tokens que se consumen cada vez que las herramientas del servidor se cargan en el contexto de un modelo. Los recuentos más altos reducen la atención disponible para otras tareas.
Instalar
Instalación con un clic
Agrega esto a tu archivo `claude_desktop_config.json`:
{
"mcpServers": {
"ngx-json-render-ui": {
"url": "https://ngx-json-render.vercel.app/mcp"
}
}
}Puntos de conexión remotos
https://ngx-json-render.vercel.app/mcpstreamable-httpQué puede hacer
Inventario de herramientas
Herramientas (1)
🟢render-ui(spec)
Render an interactive Angular Material UI inline in the chat. Pass `spec`: one complete json-render spec object (not JSON Patch lines). The input schema lists every component, its props and allowed values, and every action; use only those. - `root` is the key of the top element. `elements` is a flat map of key → { type, props, children: [child keys] }; every child key must exist in `elements`. - `state` holds the data. Read it with {"$state":"/path"} rather than repeating values in props. Data-backed UI always needs `state`; use realistic sample data. - A prop can be dynamic: {"$state":"/p"} reads, {"$bindState":"/p"} binds a form field both ways, {"$template":"Hi ${/name}"} interpolates, {"$cond":{"$state":"/p"},"$then":a,"$else":b} picks. - Lists: on a container, "repeat":{"statePath":"/items","key":"id"}; its children render once per item and read {"$item":"field"}, or ${field} inside a $template. - `visible` and `on` sit next to `props`, never inside: "visible":{"$state":"/tab","eq":"home"}, "on":{"press":{"action":"setState","params":{"statePath":"/tab","value":"home"}}}. - Forms: give inputs props.validation {"checks":[{"type":"required","message":"..."}]} and submit with submitForm, which runs its inner action only when every field is valid. - To continue the conversation from a button, use sendMessage: {"action":"sendMessage","params":{"text":"Approve release 2.4.0","data":{"$state":"/release"}}}. The host puts `text` (and `data` as JSON) in the chat as the user's message, so write it in their voice. For a form: {"action":"submitForm","params":{"action":"sendMessage","params":{"text":"Sign me up","data":{"$state":"/form"}}}}.
Esquema de entrada
{
"type": "object",
"properties": {
"spec": {
"type": "object",
"properties": {
"root": {
"type": "string",
"description": "Key of the top element in `elements`."
},
"elements": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"oneOf": [
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Stack"
},
"props": {
"type": "object",
"properties": {
"direction": {
"anyOf": [
{
"type": "string",
"enum": [
"vertical",
"horizontal"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"gap": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"padding": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"align": {
"anyOf": [
{
"type": "string",
"enum": [
"start",
"center",
"end",
"stretch"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"justify": {
"anyOf": [
{
"type": "string",
"enum": [
"start",
"center",
"between",
"end"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"wrap": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Stack: Layout container that stacks children vertically or horizontally. The primary building block — use it for every group of elements."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Grid"
},
"props": {
"type": "object",
"properties": {
"columns": {
"anyOf": [
{
"type": "number",
"minimum": 1,
"maximum": 6
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"gap": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Grid: Responsive grid that places children in equal columns, collapsing to one column on narrow screens. Use for dashboards and card galleries."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Card"
},
"props": {
"type": "object",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"subtitle": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"appearance": {
"anyOf": [
{
"type": "string",
"enum": [
"outlined",
"raised",
"filled"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Card: Material card with an optional title/subtitle header and an \"actions\" slot rendered as a footer button row."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Toolbar"
},
"props": {
"type": "object",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"color": {
"anyOf": [
{
"type": "string",
"enum": [
"primary",
"accent",
"warn"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Toolbar: Material toolbar for a page or section header. Children are placed at the trailing edge."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "ExpansionPanel"
},
"props": {
"type": "object",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"expanded": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"title"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "ExpansionPanel: Collapsible Material panel. Use for secondary detail that should not compete with the main content."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Tabs"
},
"props": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Tabs: Material tab group. Children MUST all be Tab components; each Tab supplies one tab and its body."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Tab"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"label"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Tab: A single tab inside a Tabs component. Valid only as a direct child of Tabs."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Divider"
},
"props": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Divider: Horizontal Material divider."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Heading"
},
"props": {
"type": "object",
"properties": {
"content": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"level": {
"anyOf": [
{
"type": "number",
"minimum": 1,
"maximum": 3
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"content"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Heading: Section heading (level 1–3) using the Material type scale."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Text"
},
"props": {
"type": "object",
"properties": {
"content": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"tone": {
"anyOf": [
{
"type": "string",
"enum": [
"default",
"muted",
"strong"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"content"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Text: A paragraph of body text; \"\\n\" in content starts a new line."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Icon"
},
"props": {
"type": "object",
"properties": {
"name": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"color": {
"anyOf": [
{
"type": "string",
"enum": [
"primary",
"accent",
"warn"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"name"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Icon: Material Symbols icon. `name` is the ligature, e.g. \"home\", \"check_circle\", \"warning\"."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Metric"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"value": {
"anyOf": [
{
"type": [
"string",
"number"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"delta": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"trend": {
"anyOf": [
{
"type": "string",
"enum": [
"up",
"down",
"flat"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"label",
"value"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Metric: Key metric tile with an optional delta and trend direction. Use inside a Grid for dashboard summaries."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Chip"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"color": {
"anyOf": [
{
"type": "string",
"enum": [
"primary",
"accent",
"warn"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"label"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Chip: Material chip, for tags and status labels."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "List"
},
"props": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "List: Material list container. Children MUST all be ListItem components."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "ListItem"
},
"props": {
"type": "object",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"title"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "ListItem: Row inside a List. Emits a 'press' event when clicked. Valid only as a direct child of List."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Table"
},
"props": {
"type": "object",
"properties": {
"columns": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string"
},
"header": {
"type": "string"
},
"align": {
"type": "string",
"enum": [
"start",
"end"
]
}
},
"required": [
"field",
"header"
]
}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"rows": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"columns",
"rows"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Table: Material table. `columns` describes the header; `rows` is an array of objects keyed by each column's `field`. Bind `rows` to a state array with {\"$state\":\"/path\"} rather than using repeat."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Button"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"variant": {
"anyOf": [
{
"type": "string",
"enum": [
"text",
"filled",
"elevated",
"outlined",
"tonal"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"color": {
"anyOf": [
{
"type": "string",
"enum": [
"primary",
"accent",
"warn"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"icon": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"disabled": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"label"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Button: Material button that emits a 'press' event. `variant` follows the Material 3 button appearances; use \"filled\" for the primary action on a screen and \"text\" for secondary ones. Put the action in the element's `on.press`, never in props."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "IconButton"
},
"props": {
"type": "object",
"properties": {
"icon": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"color": {
"anyOf": [
{
"type": "string",
"enum": [
"primary",
"accent",
"warn"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"disabled": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"icon",
"label"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "IconButton: Icon-only Material button that emits a 'press' event. `label` is the accessible name and is required; it is also shown as a tooltip on hover and focus."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Input"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"placeholder": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"hint": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"type": {
"anyOf": [
{
"type": "string",
"enum": [
"text",
"number",
"email",
"password"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"required": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"disabled": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"validation": {
"anyOf": [
{
"type": "object",
"properties": {
"checks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"args": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
}
},
"message": {
"type": "string"
}
},
"required": [
"type",
"message"
]
}
},
"validateOn": {
"type": "string",
"enum": [
"change",
"blur",
"submit"
]
},
"enabled": {
"allOf": [
{
"$ref": "#/definitions/__schema0"
}
]
}
}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Input: Material text field. Bind `value` with {\"$bindState\":\"/path\"} for two-way binding; emits 'submit' on Enter. `required` only draws the asterisk — enforcement comes from `validation`. Validate it with `validation`: {\"checks\":[{\"type\":\"required\",\"message\":\"...\"}],\"validateOn\":\"blur\"}. Check types: required, requiredIf, email, url, numeric, minLength, maxLength, pattern, min, max, matches, equalTo, lessThan, greaterThan. Args go in `args` (e.g. {\"type\":\"minLength\",\"args\":{\"min\":8},\"message\":\"...\"}). Validation needs a bound value. The built-in validateForm action checks every bound field at once, and submitForm checks them and then dispatches your submit action only if they all pass."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Textarea"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"placeholder": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"rows": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"disabled": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"validation": {
"anyOf": [
{
"type": "object",
"properties": {
"checks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"args": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
}
},
"message": {
"type": "string"
}
},
"required": [
"type",
"message"
]
}
},
"validateOn": {
"type": "string",
"enum": [
"change",
"blur",
"submit"
]
},
"enabled": {
"allOf": [
{
"$ref": "#/definitions/__schema0"
}
]
}
}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Textarea: Multi-line Material text field. Bind `value` with {\"$bindState\":\"/path\"}. Validate it with `validation`: {\"checks\":[{\"type\":\"required\",\"message\":\"...\"}],\"validateOn\":\"blur\"}. Check types: required, requiredIf, email, url, numeric, minLength, maxLength, pattern, min, max, matches, equalTo, lessThan, greaterThan. Args go in `args` (e.g. {\"type\":\"minLength\",\"args\":{\"min\":8},\"message\":\"...\"}). Validation needs a bound value. The built-in validateForm action checks every bound field at once, and submitForm checks them and then dispatches your submit action only if they all pass."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Select"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"options": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"value": {
"type": "string"
},
"label": {
"type": "string"
}
},
"required": [
"value",
"label"
]
}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"disabled": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"validation": {
"anyOf": [
{
"type": "object",
"properties": {
"checks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"args": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
}
},
"message": {
"type": "string"
}
},
"required": [
"type",
"message"
]
}
},
"validateOn": {
"type": "string",
"enum": [
"change",
"blur",
"submit"
]
},
"enabled": {
"allOf": [
{
"$ref": "#/definitions/__schema0"
}
]
}
}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"options"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Select: Material select. Bind `value` with {\"$bindState\":\"/path\"}; `options` is an explicit list. Validate it with `validation`: {\"checks\":[{\"type\":\"required\",\"message\":\"...\"}],\"validateOn\":\"blur\"}. Check types: required, requiredIf, email, url, numeric, minLength, maxLength, pattern, min, max, matches, equalTo, lessThan, greaterThan. Args go in `args` (e.g. {\"type\":\"minLength\",\"args\":{\"min\":8},\"message\":\"...\"}). Validation needs a bound value. The built-in validateForm action checks every bound field at once, and submitForm checks them and then dispatches your submit action only if they all pass."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Checkbox"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"checked": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"disabled": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"validation": {
"anyOf": [
{
"type": "object",
"properties": {
"checks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"args": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
}
},
"message": {
"type": "string"
}
},
"required": [
"type",
"message"
]
}
},
"validateOn": {
"type": "string",
"enum": [
"change",
"blur",
"submit"
]
},
"enabled": {
"allOf": [
{
"$ref": "#/definitions/__schema0"
}
]
}
}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"label"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Checkbox: Material checkbox. Bind `checked` with {\"$bindState\":\"/path\"} or {\"$bindItem\":\"field\"} inside a repeat. Validate it with `validation`: {\"checks\":[{\"type\":\"required\",\"message\":\"...\"}],\"validateOn\":\"blur\"}. Check types: required, requiredIf, email, url, numeric, minLength, maxLength, pattern, min, max, matches, equalTo, lessThan, greaterThan. Args go in `args` (e.g. {\"type\":\"minLength\",\"args\":{\"min\":8},\"message\":\"...\"}). Validation needs a bound value. The built-in validateForm action checks every bound field at once, and submitForm checks them and then dispatches your submit action only if they all pass."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "RadioGroup"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"options": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"value": {
"type": "string"
},
"label": {
"type": "string"
}
},
"required": [
"value",
"label"
]
}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"direction": {
"anyOf": [
{
"type": "string",
"enum": [
"vertical",
"horizontal"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"validation": {
"anyOf": [
{
"type": "object",
"properties": {
"checks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"args": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
}
},
"message": {
"type": "string"
}
},
"required": [
"type",
"message"
]
}
},
"validateOn": {
"type": "string",
"enum": [
"change",
"blur",
"submit"
]
},
"enabled": {
"allOf": [
{
"$ref": "#/definitions/__schema0"
}
]
}
}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"options"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "RadioGroup: Material radio group. Bind `value` with {\"$bindState\":\"/path\"}. Validate it with `validation`: {\"checks\":[{\"type\":\"required\",\"message\":\"...\"}],\"validateOn\":\"blur\"}. Check types: required, requiredIf, email, url, numeric, minLength, maxLength, pattern, min, max, matches, equalTo, lessThan, greaterThan. Args go in `args` (e.g. {\"type\":\"minLength\",\"args\":{\"min\":8},\"message\":\"...\"}). Validation needs a bound value. The built-in validateForm action checks every bound field at once, and submitForm checks them and then dispatches your submit action only if they all pass."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "SlideToggle"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"checked": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"disabled": {
"anyOf": [
{
"type": "boolean"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"label"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "SlideToggle: Material slide toggle for on/off settings. Bind `checked` with {\"$bindState\":\"/path\"}."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Slider"
},
"props": {
"type": "object",
"properties": {
"label": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"value": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"min": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"max": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"step": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Slider: Material slider for a numeric range. Bind `value` with {\"$bindState\":\"/path\"}."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "ProgressBar"
},
"props": {
"type": "object",
"properties": {
"value": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"mode": {
"anyOf": [
{
"type": "string",
"enum": [
"determinate",
"indeterminate"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"color": {
"anyOf": [
{
"type": "string",
"enum": [
"primary",
"accent",
"warn"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "ProgressBar: Material progress bar (0–100). Use mode \"indeterminate\" when the amount of work is unknown."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Spinner"
},
"props": {
"type": "object",
"properties": {
"diameter": {
"anyOf": [
{
"type": "number"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"color": {
"anyOf": [
{
"type": "string",
"enum": [
"primary",
"accent",
"warn"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Spinner: Material indeterminate progress spinner, for loading states."
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "Callout"
},
"props": {
"type": "object",
"properties": {
"title": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"content": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"severity": {
"anyOf": [
{
"type": "string",
"enum": [
"info",
"success",
"warning",
"error"
]
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"content"
],
"additionalProperties": false
},
"children": {
"default": [],
"type": "array",
"items": {
"type": "string"
}
},
"visible": {
"allOf": [
{
"$ref": "#/definitions/Visibility"
}
]
},
"repeat": {
"allOf": [
{
"$ref": "#/definitions/Repeat"
}
]
},
"on": {
"allOf": [
{
"$ref": "#/definitions/Events"
}
]
},
"watch": {
"allOf": [
{
"$ref": "#/definitions/Watchers"
}
]
}
},
"required": [
"type",
"props"
],
"additionalProperties": false,
"description": "Callout: Inline message block for informational, success, warning, or error text."
}
]
}
},
"state": {
"description": "Initial state model; bindings read it with {\"$state\": \"/path\"}.",
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
},
"required": [
"root",
"elements"
],
"additionalProperties": false
}
},
"required": [
"spec"
],
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"DynamicValue": {
"type": "object",
"properties": {},
"additionalProperties": {},
"description": "Dynamic value: {\"$state\"}, {\"$bindState\"}, {\"$bindItem\"}, {\"$item\"}, {\"$index\"}, {\"$template\"} or {\"$cond\",\"$then\",\"$else\"}."
},
"Visibility": {
"description": "Show the element only when this holds: {\"$state\":\"/p\",\"eq\":v} (or neq, gt, gte, lt, lte, not), an array of conditions (all), {\"$or\":[...]}, true or false."
},
"Repeat": {
"type": "object",
"properties": {
"statePath": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"key": {
"type": "string"
}
},
"required": [
"statePath"
],
"additionalProperties": false,
"description": "Render the children once per item of the state array at statePath; they read {\"$item\":\"field\"} and {\"$index\":true}."
},
"Events": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"$ref": "#/definitions/ActionBinding"
},
{
"type": "array",
"items": {
"$ref": "#/definitions/ActionBinding"
}
}
]
},
"description": "Event name (such as \"press\", \"change\" or \"submit\") → action binding."
},
"ActionBinding": {
"oneOf": [
{
"type": "object",
"properties": {
"action": {
"type": "string",
"const": "sendMessage"
},
"params": {
"type": "object",
"properties": {
"text": {
"anyOf": [
{
"type": "string"
},
{
"$ref": "#/definitions/DynamicValue"
}
]
},
"data": {
"anyOf": [
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
{
"$ref": "#/definitions/DynamicValue"
}
]
}
},
"required": [
"text"
],
"additionalProperties": false
},
"confirm": {},
"onSuccess": {},
"onError": {},
"preventDefault": {
"type": "boolean"
}
},
"required": [
"action",
"params"
],
"additionalProperties": false,
"description": "sendMessage: Send a message to you, the assistant, as the user, so the conversation continues from the UI. Params: { \"text\": \"what the user chose or asks for\", \"data\"?: { \"$state\": \"/path\" } }. `data` is optional and is attached as JSON; make it a single reference to a state object, because references nested inside `data` are not resolved. Use it for choices and follow-ups (\"Approve\", \"Show more\", a picked option). To send a form, gate it with submitForm: { \"action\": \"submitForm\", \"params\": { \"action\": \"sendMessage\", \"params\": { \"text\": \"Submit the sign-up form\", \"data\": { \"$state\": \"/form\" } } } }. The host puts the message in the chat as the user's (Claude lets the user review it and send it), so write `text` in their voice."
},
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": [
"setState",
"pushState",
"removeState",
"validateForm",
"submitForm"
]
},
"params": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"confirm": {},
"onSuccess": {},
"onError": {},
"preventDefault": {
"type": "boolean"
}
},
"required": [
"action"
],
"additionalProperties": false,
"description": "setState: Update a value in the state model at the given statePath. Params: { statePath: string, value: any }\npushState: Append an item to an array in state. Params: { statePath: string, value: any, clearStatePath?: string }. Value can contain {\"$state\":\"/path\"} refs and \"$id\" for auto IDs.\nremoveState: Remove an item from an array in state by index. Params: { statePath: string, index: number }\nvalidateForm: Validate all registered form fields and write the result to state. Params: { statePath?: string }. Defaults to /formValidation. Result: { valid: boolean, errors: Record<string, string[]> }.\nsubmitForm: Validate all registered form fields and, only if every one passes, dispatch another action. Params: { action: string, params?: object, statePath?: string }. Writes the same { valid, errors } result as validateForm. Use this on a form's submit button: it is validateForm and the submit in one binding, and the submit is skipped when the form is invalid."
}
]
},
"Watchers": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"$ref": "#/definitions/ActionBinding"
},
{
"type": "array",
"items": {
"$ref": "#/definitions/ActionBinding"
}
}
]
},
"description": "State path → action binding, run when the value at that path changes."
},
"__schema0": {
"anyOf": [
{
"type": "boolean"
},
{
"anyOf": [
{
"type": "object",
"properties": {
"$state": {
"type": "string"
},
"eq": {},
"neq": {},
"gt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"gte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"not": {
"type": "boolean",
"const": true
}
},
"required": [
"$state"
]
},
{
"type": "object",
"properties": {
"$item": {
"type": "string"
},
"eq": {},
"neq": {},
"gt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"gte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"not": {
"type": "boolean",
"const": true
}
},
"required": [
"$item"
]
},
{
"type": "object",
"properties": {
"$index": {
"type": "boolean",
"const": true
},
"eq": {},
"neq": {},
"gt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"gte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"not": {
"type": "boolean",
"const": true
}
},
"required": [
"$index"
]
}
]
},
{
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"properties": {
"$state": {
"type": "string"
},
"eq": {},
"neq": {},
"gt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"gte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"not": {
"type": "boolean",
"const": true
}
},
"required": [
"$state"
]
},
{
"type": "object",
"properties": {
"$item": {
"type": "string"
},
"eq": {},
"neq": {},
"gt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"gte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"not": {
"type": "boolean",
"const": true
}
},
"required": [
"$item"
]
},
{
"type": "object",
"properties": {
"$index": {
"type": "boolean",
"const": true
},
"eq": {},
"neq": {},
"gt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"gte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lt": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"lte": {
"anyOf": [
{
"type": "number"
},
{
"type": "object",
"properties": {
"$state": {
"type": "string"
}
},
"required": [
"$state"
]
}
]
},
"not": {
"type": "boolean",
"const": true
}
},
"required": [
"$index"
]
}
]
}
},
{
"type": "object",
"properties": {
"$and": {
"type": "array",
"items": {
"$ref": "#/definitions/__schema0"
}
}
},
"required": [
"$and"
]
},
{
"type": "object",
"properties": {
"$or": {
"type": "array",
"items": {
"$ref": "#/definitions/__schema0"
}
}
},
"required": [
"$or"
]
}
]
}
}
}Comunidad
Evidencia