{
  "$schema": "https://freesail.ai/schemas/catalog-schema-v1.json",
  "$id": "https://freesail.ai/catalogs/standard-catalog.json",
  "title": "Freesail Standard Catalog",
  "description": "Unified catalog of standard A2UI components and functions.",
  "catalogId": "https://freesail.ai/catalogs/standard-catalog.json",
  "components": {
    "Text": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "Renders text content. Key properties: text (required), variant (h1/h2/h3/h4/h5/caption/body), size (CSS font-size), weight (CSS font-weight), color (CSS color). User-Writable: false.",
          "properties": {
            "component": {
              "const": "Text"
            },
            "text": {
              "$ref": "#/$defs/DynamicString",
              "description": "The text content to display. While simple Markdown formatting is supported (i.e. without HTML, images, or links), utilizing dedicated UI components is generally preferred for a richer and more structured presentation."
            },
            "variant": {
              "type": "string",
              "description": "A hint for the base text style.",
              "enum": [
                "h1",
                "h2",
                "h3",
                "h4",
                "h5",
                "caption",
                "body"
              ]
            },
            "size": {
              "$ref": "#/$defs/DynamicString",
              "description": "CSS font-size for the text (e.g. '12px', '1.2rem', '2em'). Overrides the size implied by variant."
            },
            "fontWeight": {
              "$ref": "#/$defs/DynamicString",
              "description": "CSS font-weight (e.g. 'normal', 'bold', '500', '700'). Overrides the weight implied by variant."
            },
            "color": {
              "$ref": "#/$defs/DynamicString",
              "description": "CSS color for the text (e.g. '#ef4444', 'red', 'var(--freesail-primary)'). Defaults to inherited color."
            }
          },
          "required": [
            "component",
            "text"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Icon": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "Displays a Material Design icon. Key properties: name (required, a Material Icon name in camelCase). User-Writable: false.",
          "properties": {
            "component": {
              "const": "Icon"
            },
            "name": {
              "description": "A Material Symbols icon name in camelCase (e.g. 'home', 'search', 'settings', 'accountCircle', 'shoppingCart', 'mail', 'phone', 'star', 'language'). IMPORTANT: Material Symbols does NOT include brand or social media icons — 'facebook', 'twitter', 'instagram', 'linkedin', 'youtube' and similar are invalid and will render as broken text. For social media links, use a Button with variant 'borderless' and a text label instead.",
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "path"
                  ],
                  "additionalProperties": false
                }
              ]
            },
            "size": {
              "$ref": "#/$defs/DynamicString",
              "description": "CSS size for the icon (e.g. '12px', '1.2rem', '2em')."
            },
            "color": {
              "$ref": "#/$defs/DynamicString",
              "description": "CSS color for the icon (e.g. '#ef4444', 'red', 'var(--freesail-primary)'). Defaults to inherited color."
            }
          },
          "required": [
            "component",
            "name"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Row": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A layout component that arranges its children horizontally. To create a grid layout, nest Columns within this Row. Key properties: children (required), gap (spacing between children, default '8px'), padding, justify (start/center/end/spaceBetween/spaceAround/spaceEvenly/stretch), align (start/center/end/stretch; controls vertical alignment). User-Writable: false.",
          "properties": {
            "component": {
              "const": "Row"
            },
            "children": {
              "description": "Defines the children. Use an array of strings for a fixed set of children, or a template object to generate children from a data list. Children cannot be defined inline, they must be referred to by ID.",
              "$ref": "#/$defs/ChildList"
            },
            "gap": {
              "description": "Spacing between children. Use semantic words: \"none\", \"sm\" / \"small\", \"md\" / \"medium\", \"lg\" / \"large\", \"xl\". Also accepts any valid CSS length (e.g. \"16px\").",
              "$ref": "#/$defs/DynamicString",
              "default": "sm"
            },
            "padding": {
              "description": "Padding around the content.",
              "$ref": "#/$defs/DynamicString"
            },
            "justify": {
              "type": "string",
              "description": "Defines the arrangement of children along the main axis (horizontally). Use 'spaceBetween' to push items to the edges, or 'start'/'end'/'center' to pack them together.",
              "enum": [
                "center",
                "end",
                "spaceAround",
                "spaceBetween",
                "spaceEvenly",
                "start",
                "stretch"
              ]
            },
            "align": {
              "type": "string",
              "description": "Defines the alignment of children along the cross axis (vertically). Use 'center' to vertically center items of the same height. Use 'end' when mixing labeled inputs (TextField, Dropdown) with unlabeled components (Button) — aligns bottom edges so the button lines up with the input fields rather than the center of the label+input block.",
              "enum": [
                "start",
                "center",
                "end",
                "stretch"
              ]
            },
            "wrap": {
              "type": "string",
              "description": "Defines whether items should wrap to a new line if they exceed the container width.",
              "enum": [
                "nowrap",
                "wrap",
                "wrap-reverse"
              ]
            },
            "theme": {
              "$ref": "#/$defs/Theme",
              "description": "Theme token overrides cascading to all children of this layout container. Useful for scoping a color scheme to a section of the UI. Token-to-element mapping: bg → sets BOTH the container's own background color AND the background of any flat Card children inside (IMPORTANT: always set bg when you want a colored section background, e.g. a hero or banner — do NOT set color on individual Text children instead); bgRaised → background of raised Card children; textForeground → text color inherited by all Text components inside (use this alongside bg for hero sections so text is readable); primary → brand/accent color for Button and icon children; border → border color for Divider and TabularGrid children. Example for a dark hero section: { \"bg\": \"#1a2a4a\", \"textForeground\": \"#ffffff\" }"
            }
          },
          "required": [
            "component",
            "children"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Column": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A layout component that arranges its children vertically. To create a grid layout, nest Rows within this Column. Key properties: children (required), gap (spacing between children, default '8px'), padding, justify (start/center/end/spaceBetween/spaceAround/spaceEvenly/stretch), align (start/center/end/stretch; controls horizontal alignment of children; default is 'start'; set to 'stretch' for list layouts where children should fill the full width). User-Writable: false.",
          "properties": {
            "component": {
              "const": "Column"
            },
            "children": {
              "description": "Defines the children. Use an array of strings for a fixed set of children, or a template object to generate children from a data list. Children cannot be defined inline, they must be referred to by ID.",
              "$ref": "#/$defs/ChildList"
            },
            "gap": {
              "description": "Spacing between children. Use semantic words: \"none\", \"sm\" / \"small\", \"md\" / \"medium\", \"lg\" / \"large\", \"xl\". Also accepts any valid CSS length (e.g. \"16px\").",
              "$ref": "#/$defs/DynamicString",
              "default": "sm"
            },
            "padding": {
              "description": "Padding around the content.",
              "$ref": "#/$defs/DynamicString"
            },
            "justify": {
              "type": "string",
              "description": "Defines the arrangement of children along the main axis (vertically). Use 'spaceBetween' to push items to the edges (e.g. header at top, footer at bottom), or 'start'/'end'/'center' to pack them together.",
              "enum": [
                "start",
                "center",
                "end",
                "spaceBetween",
                "spaceAround",
                "spaceEvenly",
                "stretch"
              ]
            },
            "align": {
              "type": "string",
              "description": "Defines the alignment of children along the cross axis (horizontally). This is similar to the CSS 'align-items' property.",
              "enum": [
                "center",
                "end",
                "start",
                "stretch"
              ]
            },
            "theme": {
              "$ref": "#/$defs/Theme",
              "description": "Theme token overrides cascading to all children of this layout container. Useful for scoping a color scheme to a section of the UI. Token-to-element mapping: bg → sets BOTH the container's own background color AND the background of any flat Card children inside (IMPORTANT: always set bg when you want a colored section background, e.g. a hero or banner — do NOT set color on individual Text children instead); bgRaised → background of raised Card children; textForeground → text color inherited by all Text components inside (use this alongside bg for hero sections so text is readable); primary → brand/accent color for Button and icon children; border → border color for Divider and TabularGrid children. Example for a dark hero section: { \"bg\": \"#1a2a4a\", \"textForeground\": \"#ffffff\" }"
            }
          },
          "required": [
            "component",
            "children"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Card": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A styled container with border and optional shadow. Two variants: 'raised' (default, elevated look with shadow and rounded corners) and 'flat' (no shadow, square corners, background matches the main surface). To make cards stretch to fill their parent's width, either set width to '100%' on the Card, or set align to 'stretch' on the parent Column. Key properties: child (required), variant ('raised'|'flat'), borderWeight (border thickness in px, default 1, 0 removes border), padding, width, height, align ('start'|'center'|'end'|'stretch', aligns children horizontally), justify ('start'|'center'|'end'|'between'|'around', distributes children vertically), zoomable. User-Writable: false.",
          "properties": {
            "component": {
              "const": "Card"
            },
            "variant": {
              "type": "string",
              "enum": [
                "raised",
                "flat"
              ],
              "default": "raised",
              "description": "Visual style of the card. 'raised' (default) has a shadow and rounded corners on an elevated background. 'flat' has no shadow, square corners, and blends with the main surface background."
            },
            "borderWeight": {
              "type": "number",
              "minimum": 0,
              "default": 1,
              "description": "Border thickness in pixels. Default is 1. Set to 0 to remove the border entirely."
            },
            "padding": {
              "description": "Padding inside the card.",
              "$ref": "#/$defs/DynamicString",
              "default": "16px"
            },
            "align": {
              "type": "string",
              "enum": [
                "start",
                "center",
                "end",
                "stretch"
              ],
              "description": "Cross-axis alignment of children inside the card. 'stretch' (default) makes children fill the full card width. 'start' aligns children to the left, 'center' centers them horizontally, 'end' aligns them to the right."
            },
            "justify": {
              "type": "string",
              "enum": [
                "start",
                "center",
                "end",
                "between",
                "around"
              ],
              "description": "Main-axis (vertical) distribution of children inside the card. 'start' (default) stacks from the top, 'center' centers vertically, 'end' aligns to the bottom."
            },
            "zoomable": {
              "type": "boolean",
              "description": "When true, a small toggle button appears in the top-right corner of the card. Clicking it opens the card in a centered modal overlay at 70% of the viewport width (max 1200px, max 90vh tall); clicking outside or the button again restores it. Set it to true when the card contains content that benefits from a larger view, such as charts. "
            },
            "child": {
              "$ref": "#/$defs/ComponentId",
              "description": "The ID of the single child component to be rendered inside the card. To display multiple elements, you MUST wrap them in a layout component (like Column or Row) and pass that container's ID here. Do NOT pass multiple IDs or a non-existent ID. Do NOT define the child component inline."
            },
            "theme": {
              "$ref": "#/$defs/Theme",
              "description": "Theme token overrides for this card and all content inside it. Token-to-element mapping: bgRaised → card background when variant is 'raised' (default); bg → card background when variant is 'flat'; textForeground → primary text color inside the card; textSecondary → secondary/muted text inside the card; border → card border color; primary → accent color for primary buttons or icons inside. Example: { \"bgRaised\": \"#1e3a5f\", \"textForeground\": \"#ffffff\" }"
            }
          },
          "required": [
            "component",
            "child"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Modal": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A modal window that overlays the screen. IMPORTANT: The Modal must be added to a parent layout's children array (e.g. the root Column) to render. It renders as a fixed overlay so its position in the tree does not affect layout. You can set visibility at client side using the show/hide functions. To open the modal, use a Button whose action calls the show function with the modal's ID. Key properties: child (required, ID of the component shown inside the modal). The Modal includes a 'X' button for closing. User-Writable: false.",
          "properties": {
            "component": {
              "const": "Modal"
            },
            "child": {
              "$ref": "#/$defs/ComponentId",
              "description": "The ID of the component to be displayed inside the modal. Do NOT define the component inline."
            },
            "theme": {
              "$ref": "#/$defs/Theme",
              "description": "Theme token overrides scoped to the modal panel and all content inside it. Token-to-element mapping: bgRaised → modal panel background; textForeground → modal title and body text; border → modal border and internal dividers; primary → primary action button color inside the modal. Example: { \"bgRaised\": \"#0f172a\", \"textForeground\": \"#f8fafc\" }"
            }
          },
          "required": [
            "component",
            "child"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Button": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/Checkable"
        },
        {
          "type": "object",
          "description": "A clickable button that triggers an action. Key properties: action (required), label (text for the button), child (ID of a child component, e.g. Icon), variant (primary/secondary/outline/borderless/danger; default is 'primary' which uses the theme's primary color). User-Writable: false.",
          "properties": {
            "component": {
              "const": "Button"
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "The text label for the button. Used if 'child' is not provided."
            },
            "child": {
              "$ref": "#/$defs/ComponentId",
              "description": "The ID of the child component. Use a 'Text' component for a labeled button. Only use an 'Icon' if the requirements explicitly ask for an icon-only button. Do NOT define the child component inline."
            },
            "variant": {
              "type": "string",
              "description": "A hint for the button style. If omitted, a default button style is used.",
              "enum": [
                "primary",
                "secondary",
                "outline",
                "borderless",
                "danger"
              ],
              "default": "primary"
            },
            "action": {
              "$ref": "#/$defs/Action"
            }
          },
          "required": [
            "component",
            "action"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "TextField": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/Checkable"
        },
        {
          "type": "object",
          "description": "A text input field for user input. Key properties: value (data binding for the input's value), variant (shortText/longText/number/obscured), label (optional — shows above the input in stacked Column forms; omit for inline Row forms and use placeholder instead), placeholder (hint text inside the input), min/max (numeric bounds, only used when variant is 'number'). User-Writable: true.",
          "properties": {
            "component": {
              "const": "TextField"
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "Optional label shown above the input. Use in stacked Column forms where persistent field identification is needed. Omit in inline Row forms — use placeholder instead."
            },
            "placeholder": {
              "$ref": "#/$defs/DynamicString",
              "description": "Hint text shown inside the input when empty. Use as the primary affordance in inline Row forms. Independent of label."
            },
            "value": {
              "$ref": "#/$defs/DynamicString",
              "description": "The value of the text field."
            },
            "variant": {
              "type": "string",
              "description": "The type of input field to display.",
              "enum": [
                "longText",
                "number",
                "shortText",
                "obscured"
              ]
            },
            "min": {
              "$ref": "#/$defs/DynamicNumber",
              "description": "Minimum allowed value. Only used when variant is 'number'."
            },
            "max": {
              "$ref": "#/$defs/DynamicNumber",
              "description": "Maximum allowed value. Only used when variant is 'number'."
            }
          },
          "required": [
            "component",
            "placeholder"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "ChoicePickerSingleSelect": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/Checkable"
        },
        {
          "type": "object",
          "description": "A component that allows selecting exactly one option from a list of options. User-Writable: true.",
          "properties": {
            "component": {
              "const": "ChoicePickerSingleSelect"
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "The label for the group of options."
            },
            "variant": {
              "type": "string",
              "description": "How the choice picker should be displayed - a group of radio buttons or chips.",
              "enum": [
                "radio",
                "chips"
              ]
            },
            "options": {
              "description": "The list of available options to choose from. Can be a literal array or a data binding to a list in the data model.",
              "oneOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "description": "The text to display for this option.",
                        "$ref": "#/$defs/DynamicString"
                      },
                      "value": {
                        "type": "string",
                        "description": "The stable value associated with this option."
                      }
                    },
                    "required": [
                      "label",
                      "value"
                    ],
                    "additionalProperties": false
                  }
                },
                {
                  "$ref": "#/$defs/DataBinding"
                }
              ]
            },
            "value": {
              "$ref": "#/$defs/DynamicString",
              "description": "The currently selected value. This should be bound to a string in the data model."
            }
          },
          "required": [
            "component",
            "options",
            "value"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "ChoicePickerMultiSelect": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/Checkable"
        },
        {
          "type": "object",
          "description": "A component that allows selecting one or more options from a list of options. User-Writable: true.",
          "properties": {
            "component": {
              "const": "ChoicePickerMultiSelect"
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "The label for the group of options."
            },
            "variant": {
              "type": "string",
              "description": "How the choice picker should be displayed - a group of checkboxes or chips.",
              "enum": [
                "checkbox",
                "chips"
              ]
            },
            "options": {
              "description": "The list of available options to choose from. Can be a literal array or a data binding to a list in the data model.",
              "oneOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "description": "The text to display for this option.",
                        "$ref": "#/$defs/DynamicString"
                      },
                      "value": {
                        "type": "string",
                        "description": "The stable value associated with this option."
                      }
                    },
                    "required": [
                      "label",
                      "value"
                    ],
                    "additionalProperties": false
                  }
                },
                {
                  "$ref": "#/$defs/DataBinding"
                }
              ]
            },
            "value": {
              "$ref": "#/$defs/DynamicStringList",
              "description": "The list of currently selected values. This should be bound to a string array in the data model."
            }
          },
          "required": [
            "component",
            "options",
            "value"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "DateInput": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/Checkable"
        },
        {
          "type": "object",
          "description": "A date picker input. Supports single date or date-range (from/to) selection. Emits ISO 8601 date strings — no time component. For time selection, use a TimeInput component separately. User-Writable: true.",
          "properties": {
            "component": {
              "const": "DateInput"
            },
            "mode": {
              "type": "string",
              "enum": [
                "single",
                "range"
              ],
              "description": "Selection mode. \"single\" (default) — one date; \"range\" — two dates (from and to)."
            },
            "value": {
              "$ref": "#/$defs/DynamicStringList",
              "description": "Array of ISO 8601 date strings (\"YYYY-MM-DD\") bound to the data model. For mode \"single\": one element [\"YYYY-MM-DD\"]. For mode \"range\": one element while the user is picking the start, two elements [\"YYYY-MM-DD\", \"YYYY-MM-DD\"] once the range is complete. Always use a DataBinding — initialise to [] in the data model."
            },
            "min": {
              "allOf": [
                {
                  "$ref": "#/$defs/DynamicString"
                },
                {
                  "if": {
                    "type": "string"
                  },
                  "then": {
                    "oneOf": [
                      {
                        "format": "date"
                      },
                      {
                        "format": "time"
                      },
                      {
                        "format": "date-time"
                      }
                    ]
                  }
                }
              ],
              "description": "The earliest selectable date in ISO 8601 format (\"YYYY-MM-DD\")."
            },
            "max": {
              "allOf": [
                {
                  "$ref": "#/$defs/DynamicString"
                },
                {
                  "if": {
                    "type": "string"
                  },
                  "then": {
                    "oneOf": [
                      {
                        "format": "date"
                      },
                      {
                        "format": "time"
                      },
                      {
                        "format": "date-time"
                      }
                    ]
                  }
                }
              ],
              "description": "The latest selectable date in ISO 8601 format (\"YYYY-MM-DD\")."
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "The text label for the input field."
            }
          },
          "required": [
            "component",
            "value"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "TimeInput": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/Checkable"
        },
        {
          "type": "object",
          "description": "A standalone time picker input with hour/minute spinners. Use this alongside a DateInput (date-only) when you need separate date and time controls — e.g., one date field plus separate start-time and end-time fields. User-Writable: true.",
          "properties": {
            "component": {
              "const": "TimeInput"
            },
            "value": {
              "$ref": "#/$defs/DynamicStringList",
              "description": "Single-element array holding the selected time as \"HH:MM\" in 24-hour format (e.g. [\"14:30\"]). Always use a DataBinding — the path should hold a string array in the data model, initialised to []."
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "The text label displayed above the spinner."
            },
            "timeStep": {
              "oneOf": [
                {
                  "type": "number",
                  "minimum": 1,
                  "maximum": 60
                },
                {
                  "$ref": "#/$defs/DataBinding"
                }
              ],
              "description": "Minute increment for the minute spinner (default 1). Use 15 or 30 for slot-based time selection."
            },
            "timeFormat": {
              "oneOf": [
                {
                  "type": "string",
                  "enum": [
                    "24h",
                    "12h"
                  ]
                },
                {
                  "$ref": "#/$defs/DataBinding"
                }
              ],
              "description": "Display format: \"24h\" (default, 00–23) or \"12h\" (1–12 with AM/PM toggle)."
            }
          },
          "required": [
            "component",
            "value"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Spacer": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "An empty space component used for layout and spacing. User-Writable: false.",
          "properties": {
            "component": {
              "const": "Spacer"
            }
          },
          "required": [
            "component"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Image": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "Displays an image. Key properties: url (required), fit (contain/cover/fill/none/scale-down), variant (icon/avatar/smallFeature/mediumFeature/largeFeature/header). User-Writable: false.",
          "properties": {
            "component": {
              "const": "Image"
            },
            "url": {
              "$ref": "#/$defs/DynamicString",
              "description": "The URL of the image to display."
            },
            "fit": {
              "type": "string",
              "description": "Specifies how the image should be resized to fit its container. This corresponds to the CSS 'object-fit' property.",
              "enum": [
                "contain",
                "cover",
                "fill",
                "none",
                "scale-down"
              ]
            },
            "variant": {
              "type": "string",
              "description": "A hint for the image size and style.",
              "enum": [
                "icon",
                "avatar",
                "smallFeature",
                "mediumFeature",
                "largeFeature",
                "header"
              ]
            }
          },
          "required": [
            "component",
            "url"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Video": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "Plays a video. Key properties: url (required), embed (set to true for YouTube/Vimeo URLs). User-Writable: false.",
          "properties": {
            "component": {
              "const": "Video"
            },
            "url": {
              "$ref": "#/$defs/DynamicString",
              "description": "The URL of the video to display."
            },
            "embed": {
              "type": "boolean",
              "description": "When true, the video is rendered inside an iframe. This MUST be set to true for third-party sources such as YouTube (youtube.com, youtu.be) and Vimeo (vimeo.com). When false or omitted, a native video player is used, which only works with direct video file URLs (e.g. .mp4, .webm).",
              "default": false
            }
          },
          "required": [
            "component",
            "url"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "AudioPlayer": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "An audio player that supports direct audio file URLs and embedded third-party players (e.g. Spotify, SoundCloud). User-Writable: false.",
          "properties": {
            "component": {
              "const": "AudioPlayer"
            },
            "url": {
              "$ref": "#/$defs/DynamicString",
              "description": "The URL of the audio to be played."
            },
            "description": {
              "description": "A description of the audio, such as a title or summary.",
              "$ref": "#/$defs/DynamicString"
            },
            "embed": {
              "type": "boolean",
              "description": "When true, the audio is rendered inside an iframe embed player. This MUST be set to true for third-party sources such as Spotify (open.spotify.com) and SoundCloud (soundcloud.com). When false or omitted, a native audio player is used, which only works with direct audio file URLs (e.g. .mp3, .wav).",
              "default": false
            }
          },
          "required": [
            "component",
            "url"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "List": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A scrollable list that lays out children vertically or horizontally, with optional alignment control. User-Writable: false.",
          "properties": {
            "component": {
              "const": "List"
            },
            "children": {
              "description": "Defines the children. Use an array of strings for a fixed set of children, or a template object to generate children from a data list.",
              "$ref": "#/$defs/ChildList"
            },
            "direction": {
              "type": "string",
              "description": "The direction in which the list items are laid out.",
              "enum": [
                "vertical",
                "horizontal"
              ]
            },
            "align": {
              "type": "string",
              "description": "Defines the alignment of children along the cross axis.",
              "enum": [
                "start",
                "center",
                "end",
                "stretch"
              ]
            }
          },
          "required": [
            "component",
            "children"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "TabGroup": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A tabbed container that shows one Tab child at a time. Children must be Tab components. User-Writable: false.",
          "properties": {
            "component": {
              "const": "TabGroup"
            },
            "children": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/ComponentId"
              },
              "description": "Array of Tab component IDs. Do NOT define components inline."
            }
          },
          "required": [
            "component",
            "children"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Tab": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A single tab within a TabGroup. Has a title and a child component. User-Writable: false.",
          "properties": {
            "component": {
              "const": "Tab"
            },
            "title": {
              "$ref": "#/$defs/DynamicString",
              "description": "The tab title displayed in the tab bar."
            },
            "child": {
              "$ref": "#/$defs/ComponentId",
              "description": "The ID of the child component. Do NOT define the component inline."
            }
          },
          "required": [
            "component",
            "title",
            "child"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Divider": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A visual separator line. Key properties: axis (horizontal/vertical, default horizontal). User-Writable: false.",
          "properties": {
            "component": {
              "const": "Divider"
            },
            "axis": {
              "type": "string",
              "description": "The orientation of the divider.",
              "enum": [
                "horizontal",
                "vertical"
              ],
              "default": "horizontal"
            }
          },
          "required": [
            "component"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Dropdown": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/Checkable"
        },
        {
          "type": "object",
          "description": "A dropdown (select) component for choosing a single option from a list. User-Writable: true.",
          "properties": {
            "component": {
              "const": "Dropdown"
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "Optional label shown above the dropdown. Use in stacked Column forms. Omit in inline Row forms or inside a TabularGrid — the context already communicates the field purpose."
            },
            "placeholder": {
              "$ref": "#/$defs/DynamicString",
              "description": "Hint text shown as the first disabled option when nothing is selected. Defaults to 'Select an option'."
            },
            "options": {
              "description": "The list of available options to choose from. Can be a literal array or a data binding to a list in the data model.",
              "oneOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "description": "The text to display for this option.",
                        "$ref": "#/$defs/DynamicString"
                      },
                      "value": {
                        "type": "string",
                        "description": "The stable value associated with this option."
                      }
                    },
                    "required": [
                      "label",
                      "value"
                    ],
                    "additionalProperties": false
                  }
                },
                {
                  "$ref": "#/$defs/DataBinding"
                }
              ]
            },
            "value": {
              "$ref": "#/$defs/DynamicString",
              "description": "The currently selected value. This should be bound to a string in the data model."
            }
          },
          "required": [
            "component",
            "options",
            "value"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "CheckBox": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/Checkable"
        },
        {
          "type": "object",
          "description": "A checkbox toggle for boolean values. Key properties: label (required), value (required, data binding for the checked state). User-Writable: true.",
          "properties": {
            "component": {
              "const": "CheckBox"
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "The text to display next to the checkbox."
            },
            "value": {
              "$ref": "#/$defs/DynamicBoolean",
              "description": "The current state of the checkbox (true for checked, false for unchecked)."
            }
          },
          "required": [
            "component",
            "label",
            "value"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Slider": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "$ref": "#/$defs/Checkable"
        },
        {
          "type": "object",
          "description": "A slider for selecting a numeric value within a range, or a range slider with multiple thumbs. Key properties: value (required), min (required), max (required), label, step. For a single thumb pass a number or DataBinding returning a number. For multi-thumb pass an array of numbers (e.g. [20, 80]) — the path binding should hold a number array. User-Writable: true.",
          "properties": {
            "component": {
              "const": "Slider"
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "The label for the slider."
            },
            "min": {
              "type": "number",
              "description": "The minimum value of the slider."
            },
            "max": {
              "type": "number",
              "description": "The maximum value of the slider."
            },
            "step": {
              "type": "number",
              "description": "The step increment. Defaults to 1."
            },
            "value": {
              "description": "The current value(s) of the slider. Pass a single number (or DataBinding returning a number) for one thumb. Pass an array of numbers for a range/multi-thumb slider — the bound path should hold a number array.",
              "oneOf": [
                {
                  "$ref": "#/$defs/DynamicNumber"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "number"
                  },
                  "minItems": 2,
                  "maxItems": 4
                }
              ]
            }
          },
          "required": [
            "component",
            "value",
            "min",
            "max"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "FluidGrid": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A responsive auto-fill grid that flows children into equal-width columns. Each column is at least minItemWidth wide; the browser fills as many columns as fit. Use for card galleries, icon grids, and any layout where items should wrap responsively. Key properties: minItemWidth (minimum column width, default '200px'), gap (space between items). User-Writable: false.",
          "properties": {
            "component": {
              "const": "FluidGrid"
            },
            "children": {
              "description": "Defines the item content. Use a template object { componentId, path } to generate items from a data list, or an array of component IDs for static children.",
              "$ref": "#/$defs/ChildList"
            },
            "minItemWidth": {
              "description": "Minimum width of each auto-fill column. Defaults to '200px'. Use CSS length values e.g. '160px', '12rem'.",
              "$ref": "#/$defs/DynamicString",
              "default": "200px"
            },
            "gap": {
              "description": "Gap between grid items. Defaults to var(--freesail-space-sm, 8px). Use CSS length or spacing token.",
              "$ref": "#/$defs/DynamicString"
            }
          },
          "required": [
            "component",
            "children"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "TabularGrid": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "A fixed-column grid with optional header row and styled alternating rows. Use columns to set a fixed column count without headers (e.g. a chess board). Use headers to render a header row — its length takes precedence over columns. Collapses to a single column on narrow containers (< 480px). Compose row content using Row and Text components via the children template. IMPORTANT: Row padding is controlled by rowPadding on the TabularGrid, not by padding on the child Row components. IMPORTANT: When placing TextField or Dropdown components inside a TabularGrid, always set hideLabel: true on each one. User-Writable: false.",
          "properties": {
            "component": {
              "const": "TabularGrid"
            },
            "columns": {
              "type": "number",
              "description": "Fixed column count. Required when headers is absent. Ignored when headers is provided (header length takes precedence)."
            },
            "headers": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/DynamicString"
              },
              "description": "Column header labels. When provided, renders a header row and its length sets the column count. Optional — omit when using columns instead."
            },
            "children": {
              "description": "Defines the row/item content. Use a template object { componentId, path } to generate items from a data list, or an array of component IDs for static children.",
              "$ref": "#/$defs/ChildList"
            },
            "columnWeights": {
              "type": "array",
              "items": {
                "type": "number"
              },
              "description": "Fractional width weights per column. Length must match column count. Defaults to equal sizing."
            },
            "showGridLines": {
              "type": "boolean",
              "description": "When true (default), draws a 1px border-bottom separator between rows. Set to false for grids where per-cell backgrounds provide the visual structure (e.g. a chess board with per-cell background props).",
              "default": true
            },
            "showBorder": {
              "type": "boolean",
              "description": "When true (default), wraps the grid in a 1px solid border with rounded corners. Set to false to remove the border.",
              "default": true
            },
            "theme": {
              "$ref": "#/$defs/Theme",
              "description": "Theme token overrides for this grid and all descendants. Token-to-element mapping: bgMuted → header row background; bgRaised → odd data row background; bg → even data row background; textSecondary → header label text color; textForeground → data cell text color; border → row separators and outer border. Example: { \"bgMuted\": \"#1e3a5f\", \"bgRaised\": \"#1e3a5f\", \"bg\": \"#162d4a\", \"textForeground\": \"#ffffff\", \"border\": \"#2d5a8e\" }"
            },
            "rowPadding": {
              "description": "CSS padding applied to every cell in each data row. Defaults to '10px 16px'.",
              "$ref": "#/$defs/DynamicString",
              "default": "10px 16px"
            },
            "gap": {
              "description": "Gap between grid items. Use CSS length or spacing token.",
              "$ref": "#/$defs/DynamicString"
            }
          },
          "required": [
            "component",
            "children"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "BarChart": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "Renders a bar chart from an array of data points. Each data point has a label and value. The chart auto-scales to fit. Use orientation 'horizontal' for long labels or many categories. User-Writable: false.",
          "properties": {
            "component": {
              "const": "BarChart"
            },
            "title": {
              "$ref": "#/$defs/DynamicString",
              "description": "Optional chart title displayed above the chart."
            },
            "data": {
              "description": "Array of data points. Each item has a 'label' (string) and 'value' (number), and optionally a 'color' (CSS color string) to override the default bar color for that item.",
              "oneOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "type": "string"
                      },
                      "value": {
                        "type": "number"
                      },
                      "color": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "label",
                      "value"
                    ]
                  },
                  "minItems": 1
                },
                {
                  "$ref": "#/$defs/DataBinding"
                }
              ]
            },
            "orientation": {
              "type": "string",
              "description": "Bar direction. 'vertical' = bars grow upward, 'horizontal' = bars grow rightward.",
              "enum": [
                "vertical",
                "horizontal"
              ],
              "default": "vertical"
            },
            "color": {
              "$ref": "#/$defs/DynamicString",
              "description": "Default bar color (CSS). Individual data items can override with their own 'color'."
            },
            "showValues": {
              "$ref": "#/$defs/DynamicBoolean",
              "description": "Whether to display the numeric value on each bar.",
              "default": true
            },
            "chartHeight": {
              "$ref": "#/$defs/DynamicNumber",
              "description": "Chart height in pixels.",
              "default": 300
            }
          },
          "required": [
            "component",
            "data"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "LineChart": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "Renders a line chart from an array of data points. Supports optional area fill and data point dots. Good for showing trends over time. User-Writable: false.",
          "properties": {
            "component": {
              "const": "LineChart"
            },
            "title": {
              "$ref": "#/$defs/DynamicString",
              "description": "Optional chart title displayed above the chart."
            },
            "data": {
              "description": "Array of data points. Each item has a 'label' (string) and 'value' (number).",
              "oneOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "type": "string"
                      },
                      "value": {
                        "type": "number"
                      }
                    },
                    "required": [
                      "label",
                      "value"
                    ]
                  },
                  "minItems": 2
                },
                {
                  "$ref": "#/$defs/DataBinding"
                }
              ]
            },
            "color": {
              "$ref": "#/$defs/DynamicString",
              "description": "Line color (CSS).",
              "default": "#2563eb"
            },
            "showDots": {
              "$ref": "#/$defs/DynamicBoolean",
              "description": "Whether to show data point circles on the line.",
              "default": true
            },
            "showArea": {
              "$ref": "#/$defs/DynamicBoolean",
              "description": "Whether to fill the area under the line with a translucent gradient.",
              "default": false
            },
            "chartHeight": {
              "$ref": "#/$defs/DynamicNumber",
              "description": "Chart height in pixels.",
              "default": 300
            }
          },
          "required": [
            "component",
            "data"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "PieChart": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "Renders a pie or donut chart from an array of segments. Each segment has a label and value. Colors are auto-assigned if not provided. User-Writable: false.",
          "properties": {
            "component": {
              "const": "PieChart"
            },
            "title": {
              "$ref": "#/$defs/DynamicString",
              "description": "Optional chart title displayed above the chart."
            },
            "data": {
              "description": "Array of segments. Each item has a 'label' (string) and 'value' (number), and optionally a 'color' (CSS color string).",
              "oneOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "type": "string"
                      },
                      "value": {
                        "type": "number"
                      },
                      "color": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "label",
                      "value"
                    ]
                  },
                  "minItems": 1
                },
                {
                  "$ref": "#/$defs/DataBinding"
                }
              ]
            },
            "donut": {
              "$ref": "#/$defs/DynamicBoolean",
              "description": "If true, renders as a donut chart with a hollow center.",
              "default": false
            },
            "size": {
              "$ref": "#/$defs/DynamicNumber",
              "description": "Chart diameter in pixels.",
              "default": 250
            },
            "align": {
              "type": "string",
              "enum": [
                "start",
                "center",
                "end"
              ],
              "description": "Horizontal alignment of the chart within its container. Default is 'start' (left-aligned)."
            }
          },
          "required": [
            "component",
            "data"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "Sparkline": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "Renders a compact inline sparkline chart from an array of numbers. Use inside StatCard or alongside text to show a quick trend. User-Writable: false.",
          "properties": {
            "component": {
              "const": "Sparkline"
            },
            "values": {
              "description": "Array of numeric values representing the trend data.",
              "oneOf": [
                {
                  "type": "array",
                  "items": {
                    "type": "number"
                  },
                  "minItems": 2
                },
                {
                  "$ref": "#/$defs/DataBinding"
                }
              ]
            },
            "color": {
              "$ref": "#/$defs/DynamicString",
              "description": "Line color (CSS).",
              "default": "#2563eb"
            }
          },
          "required": [
            "component",
            "values"
          ]
        }
      ],
      "unevaluatedProperties": false
    },
    "StatCard": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/ComponentCommon"
        },
        {
          "type": "object",
          "description": "Renders a KPI / summary statistic card with a large value, label, and optional trend indicator. Use multiple StatCards in a Row to create a dashboard header. User-Writable: false.",
          "properties": {
            "component": {
              "const": "StatCard"
            },
            "label": {
              "$ref": "#/$defs/DynamicString",
              "description": "The metric label (e.g. 'Total Revenue', 'Active Users')."
            },
            "value": {
              "$ref": "#/$defs/DynamicString",
              "description": "The formatted display value (e.g. '$12,340', '1.2k', '98%'). Use formatNumber or formatCurrency to produce this."
            },
            "trend": {
              "type": "string",
              "description": "Direction of the trend arrow.",
              "enum": [
                "up",
                "down",
                "neutral"
              ]
            },
            "trendColor": {
              "$ref": "#/$defs/DynamicString",
              "description": "Color of the trend arrow."
            },
            "trendValue": {
              "$ref": "#/$defs/DynamicString",
              "description": "The trend change text shown next to the arrow (e.g. '+12%', '-3.2%')."
            },
            "color": {
              "$ref": "#/$defs/DynamicString",
              "description": "Accent color for the card's left border and icon."
            },
            "children": {
              "$ref": "#/$defs/ChildList",
              "description": "Optional children rendered below the stat value (e.g. a Sparkline)."
            }
          },
          "required": [
            "component",
            "label",
            "value"
          ]
        }
      ],
      "unevaluatedProperties": false
    }
  },
  "functions": {
    "required": {
      "type": "object",
      "description": "Checks that the value is not null, undefined, or empty.",
      "properties": {
        "call": {
          "const": "required"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "value"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "regex": {
      "type": "object",
      "description": "Checks that the value matches a regular expression string.",
      "properties": {
        "call": {
          "const": "regex"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicValue"
            },
            "pattern": {
              "type": "string",
              "description": "The regex pattern to match against."
            }
          },
          "required": [
            "value",
            "pattern"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "checkLength": {
      "type": "object",
      "description": "Returns true if the string or array length satisfies the given constraints. Takes two arguments: the value and an object with optional 'min' and/or 'max' integer properties. Example: checkLength(value, {min: 8}) returns true if value has at least 8 characters. Always returns a boolean. To get the length as a number, use getLength instead.",
      "properties": {
        "call": {
          "const": "checkLength"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicValue"
            },
            "constraints": {
              "type": "object",
              "properties": {
                "min": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "The minimum allowed length."
                },
                "max": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "The maximum allowed length."
                }
              },
              "anyOf": [
                {
                  "required": [
                    "min"
                  ]
                },
                {
                  "required": [
                    "max"
                  ]
                }
              ]
            }
          },
          "required": [
            "value",
            "constraints"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "getLength": {
      "type": "object",
      "description": "Returns the number of characters in a value. If the value is a string, returns its length. If the value is a number or date, converts it to a string first and returns the length of that string. If the value is an array, returns the number of elements. Returns 0 for null or undefined. Use this when you need the length as a number (e.g. for comparisons with gte). Use checkLength instead if you just need to validate min/max constraints.",
      "properties": {
        "call": {
          "const": "getLength"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "value"
          ]
        },
        "returnType": {
          "const": "number"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "numeric": {
      "type": "object",
      "description": "Returns true if the numeric value satisfies the given constraints. Takes two arguments: the value and an object with optional 'min' and/or 'max' number properties. Example: numeric(value, {min: 0, max: 100}) returns true if value is between 0 and 100. Always returns a boolean.",
      "properties": {
        "call": {
          "const": "numeric"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicValue"
            },
            "constraints": {
              "type": "object",
              "properties": {
                "min": {
                  "type": "number",
                  "description": "The minimum allowed value."
                },
                "max": {
                  "type": "number",
                  "description": "The maximum allowed value."
                }
              },
              "anyOf": [
                {
                  "required": [
                    "min"
                  ]
                },
                {
                  "required": [
                    "max"
                  ]
                }
              ]
            }
          },
          "required": [
            "value",
            "constraints"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "email": {
      "type": "object",
      "description": "Checks that the value is a valid email address.",
      "properties": {
        "call": {
          "const": "email"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "value"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "formatString": {
      "type": "object",
      "description": "Performs string interpolation of data model values and other functions in the catalog functions list and returns the resulting string. The value string can contain interpolated expressions in the `${expression}` format. Supported expression types include: JSON Pointer paths to the data model (e.g., `${/absolute/path}` or `${relative/path}`), and client-side function calls (e.g., `${now()}`). Function arguments must be literals (quoted strings, numbers, booleans) or nested expressions (e.g., `${formatDate(${/currentDate}, 'MM-dd')}`). To include a literal `${` sequence, escape it as `\\${`.",
      "properties": {
        "call": {
          "const": "formatString"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "description": "The format string.",
              "type": "string"
            }
          },
          "required": [
            "value"
          ],
          "additionalProperties": {
            "$ref": "#/$defs/DynamicValue"
          }
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "formatNumber": {
      "type": "object",
      "description": "Formats a number with the specified grouping and decimal precision.",
      "properties": {
        "call": {
          "const": "formatNumber"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicNumber",
              "description": "The number to format."
            },
            "fractionDigits": {
              "$ref": "#/$defs/DynamicNumber",
              "description": "Optional. The number of decimal places to show. Defaults to 0 or 2 depending on locale."
            },
            "useGrouping": {
              "$ref": "#/$defs/DynamicBoolean",
              "description": "Optional. If true, uses locale-specific grouping separators (e.g. '1,000'). If false, returns raw digits (e.g. '1000'). Defaults to true."
            }
          },
          "required": [
            "value"
          ]
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "formatCurrency": {
      "type": "object",
      "description": "Formats a number as a currency string.",
      "properties": {
        "call": {
          "const": "formatCurrency"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicNumber",
              "description": "The monetary amount."
            },
            "currency": {
              "$ref": "#/$defs/DynamicString",
              "description": "The ISO 4217 currency code (e.g., 'USD', 'EUR')."
            }
          },
          "required": [
            "value",
            "currency"
          ]
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "formatDate": {
      "type": "object",
      "description": "Formats a timestamp into a string using a pattern.",
      "properties": {
        "call": {
          "const": "formatDate"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicValue",
              "description": "The date to format."
            },
            "pattern": {
              "$ref": "#/$defs/DynamicString",
              "description": "A Unicode TR35 date pattern string.\n\nToken Reference:\n- Year: 'yy' (26), 'yyyy' (2026)\n- Month: 'M' (1), 'MM' (01), 'MMM' (Jan), 'MMMM' (January)\n- Day: 'd' (1), 'dd' (01), 'E' (Tue), 'EEEE' (Tuesday)\n- Hour (12h): 'h' (1-12), 'hh' (01-12) - requires 'a' for AM/PM\n- Hour (24h): 'H' (0-23), 'HH' (00-23) - Military Time\n- Minute: 'mm' (00-59)\n- Second: 'ss' (00-59)\n- Period: 'a' (AM/PM)\n\nExamples:\n- 'MMM dd, yyyy' -> 'Jan 16, 2026'\n- 'HH:mm' -> '14:30' (Military)\n- 'h:mm a' -> '2:30 PM'\n- 'EEEE, d MMMM' -> 'Friday, 16 January'"
            }
          },
          "required": [
            "value",
            "pattern"
          ]
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "pluralize": {
      "type": "object",
      "description": "Returns a localized string based on the Common Locale Data Repository (CLDR) plural category of the count (zero, one, two, few, many, other). Requires an 'other' fallback. For English, just use 'one' and 'other'.",
      "properties": {
        "call": {
          "const": "pluralize"
        },
        "args": {
          "type": "object",
          "properties": {
            "count": {
              "$ref": "#/$defs/DynamicNumber",
              "description": "The numeric value used to determine the plural category."
            },
            "forms": {
              "type": "object",
              "description": "A map of CLDR plural categories to their corresponding strings.",
              "properties": {
                "zero": {
                  "$ref": "#/$defs/DynamicString",
                  "description": "String for the 'zero' category (e.g., 0 items)."
                },
                "one": {
                  "$ref": "#/$defs/DynamicString",
                  "description": "String for the 'one' category (e.g., 1 item)."
                },
                "two": {
                  "$ref": "#/$defs/DynamicString",
                  "description": "String for the 'two' category (used in Arabic, Welsh, etc.)."
                },
                "few": {
                  "$ref": "#/$defs/DynamicString",
                  "description": "String for the 'few' category (e.g., small groups in Slavic languages)."
                },
                "many": {
                  "$ref": "#/$defs/DynamicString",
                  "description": "String for the 'many' category (e.g., large groups in various languages)."
                },
                "other": {
                  "$ref": "#/$defs/DynamicString",
                  "description": "The default/fallback string (used for general plural cases)."
                }
              },
              "required": [
                "other"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "count",
            "forms"
          ]
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "now": {
      "type": "object",
      "description": "Returns the current date and time as an ISO 8601 string.",
      "properties": {
        "call": {
          "const": "now"
        },
        "returnType": {
          "const": "string"
        }
      },
      "required": [
        "call"
      ],
      "unevaluatedProperties": false
    },
    "openUrl": {
      "type": "object",
      "description": "Opens the specified URL in a browser or handler. This function has no return value.",
      "properties": {
        "call": {
          "const": "openUrl"
        },
        "args": {
          "type": "object",
          "properties": {
            "url": {
              "type": "string",
              "format": "uri",
              "description": "The URL to open."
            }
          },
          "required": [
            "url"
          ]
        },
        "returnType": {
          "const": "void"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "and": {
      "type": "object",
      "description": "Returns true if all arguments are truthy.",
      "properties": {
        "call": {
          "const": "and"
        },
        "args": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/$defs/DynamicValue"
          }
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "or": {
      "type": "object",
      "description": "Returns true if any argument is truthy.",
      "properties": {
        "call": {
          "const": "or"
        },
        "args": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/$defs/DynamicValue"
          }
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "isEmpty": {
      "type": "object",
      "description": "Returns true if the value is null, undefined, empty string, empty array, or empty object.",
      "properties": {
        "call": {
          "const": "isEmpty"
        },
        "args": {
          "type": "object",
          "properties": {
            "value": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "value"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "eq": {
      "type": "object",
      "description": "Returns true if the two values are strictly equal.",
      "properties": {
        "call": {
          "const": "eq"
        },
        "args": {
          "type": "object",
          "properties": {
            "a": {
              "$ref": "#/$defs/DynamicValue"
            },
            "b": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "a",
            "b"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "neq": {
      "type": "object",
      "description": "Returns true if the two values are not equal.",
      "properties": {
        "call": {
          "const": "neq"
        },
        "args": {
          "type": "object",
          "properties": {
            "a": {
              "$ref": "#/$defs/DynamicValue"
            },
            "b": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "a",
            "b"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "gt": {
      "type": "object",
      "description": "Returns true if the first value is greater than the second (converted to numbers).",
      "properties": {
        "call": {
          "const": "gt"
        },
        "args": {
          "type": "object",
          "properties": {
            "a": {
              "$ref": "#/$defs/DynamicValue"
            },
            "b": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "a",
            "b"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "gte": {
      "type": "object",
      "description": "Returns true if the first value is greater than or equal to the second (converted to numbers).",
      "properties": {
        "call": {
          "const": "gte"
        },
        "args": {
          "type": "object",
          "properties": {
            "a": {
              "$ref": "#/$defs/DynamicValue"
            },
            "b": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "a",
            "b"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "lt": {
      "type": "object",
      "description": "Returns true if the first value is less than the second (converted to numbers).",
      "properties": {
        "call": {
          "const": "lt"
        },
        "args": {
          "type": "object",
          "properties": {
            "a": {
              "$ref": "#/$defs/DynamicValue"
            },
            "b": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "a",
            "b"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "lte": {
      "type": "object",
      "description": "Returns true if the first value is less than or equal to the second (converted to numbers).",
      "properties": {
        "call": {
          "const": "lte"
        },
        "args": {
          "type": "object",
          "properties": {
            "a": {
              "$ref": "#/$defs/DynamicValue"
            },
            "b": {
              "$ref": "#/$defs/DynamicValue"
            }
          },
          "required": [
            "a",
            "b"
          ]
        },
        "returnType": {
          "const": "boolean"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "show": {
      "type": "object",
      "description": "Shows a component by its ID. Use this to make Modals or any other component visible.",
      "properties": {
        "call": {
          "const": "show"
        },
        "args": {
          "type": "object",
          "properties": {
            "componentId": {
              "type": "string",
              "description": "The ID of the component to show."
            }
          },
          "required": [
            "componentId"
          ]
        },
        "returnType": {
          "const": "void"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    },
    "hide": {
      "type": "object",
      "description": "Hides a component by its ID. Use this to hide Modals or any other component.",
      "properties": {
        "call": {
          "const": "hide"
        },
        "args": {
          "type": "object",
          "properties": {
            "componentId": {
              "type": "string",
              "description": "The ID of the component to hide."
            }
          },
          "required": [
            "componentId"
          ]
        },
        "returnType": {
          "const": "void"
        }
      },
      "required": [
        "call",
        "args"
      ],
      "unevaluatedProperties": false
    }
  },
  "$defs": {
    "ComponentCommon": {
      "type": "object",
      "properties": {
        "id": {
          "$ref": "#/$defs/ComponentId"
        },
        "component": {
          "type": "string",
          "description": "REQUIRED. The component type name (e.g. 'Text', 'Button', 'Column'). Each component's schema further constrains this to its exact const value."
        },
        "accessibility": {
          "$ref": "#/$defs/AccessibilityAttributes"
        },
        "visible": {
          "$ref": "#/$defs/DynamicBoolean",
          "description": "Controls whether the component is rendered. Defaults to true. Use a function call to compute dynamically (e.g. show return date only when trip type is round-trip).",
          "default": true
        },
        "width": {
          "$ref": "#/$defs/DynamicString",
          "description": "The width of the component. Use '100%' to fill the parent container's full width (e.g. on an Image or a full-width input). Use px only for small fixed-size elements (e.g. '40px' for an avatar). To distribute space proportionally between siblings in a Row/Column, use 'weight' instead of a percentage width."
        },
        "height": {
          "$ref": "#/$defs/DynamicString",
          "description": "The height of the component. Use '100%' to stretch and fill the parent container's full height. Use px only for small fixed-size elements (e.g. '40px' for an icon). To guarantee a minimum visual height (e.g. for a chart), prefer 'minHeight' over a fixed height so the component can still grow."
        },
        "weight": {
          "$ref": "#/$defs/DynamicNumber",
          "description": "The relative weight of this component within a Row or Column. This is similar to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column."
        },
        "flexBasis": {
          "$ref": "#/$defs/DynamicString",
          "description": "The flex-basis of this component within a Row or Column. Defines the default size of an element before remaining space is distributed. Essential for fluid responsive breakpoints (e.g., '300px')."
        },
        "minWidth": {
          "$ref": "#/$defs/DynamicString",
          "description": "Hard minimum width floor. The component will not shrink below this value even after wrapping. Use independently from flexBasis to prevent overflow (e.g. flexBasis: '400px' sets the wrap point, minWidth: '200px' sets the floor after wrapping)."
        },
        "minHeight": {
          "$ref": "#/$defs/DynamicString",
          "description": "Hard minimum height floor. Ensures the component has a minimum visual presence even with sparse content (e.g. '300px' for a chart card)."
        }
      },
      "required": [
        "id",
        "component"
      ]
    },
    "ComponentId": {
      "type": "string",
      "description": "The unique identifier for a component, used for both definitions and references within the same surface."
    },
    "AccessibilityAttributes": {
      "type": "object",
      "description": "Attributes to enhance accessibility when using assistive technologies like screen readers.",
      "properties": {
        "label": {
          "$ref": "#/$defs/DynamicString",
          "description": "A short string, typically 1 to 3 words, used by assistive technologies to convey the purpose or intent of an element. For example, an input field might have an accessible label of 'User ID' or a button might be labeled 'Submit'."
        },
        "description": {
          "$ref": "#/$defs/DynamicString",
          "description": "Additional information provided by assistive technologies about an element such as instructions, format requirements, or result of an action. For example, a mute button might have a label of 'Mute' and a description of 'Silences notifications about this conversation'."
        }
      }
    },
    "DynamicString": {
      "description": "A string value. Prefer a plain string literal for static text (e.g. \"Submit\"). Use a DataBinding ({\"path\": \"...\"}) to read a value from the data model. Use a formatString function call when you need to embed data model values inside a string template (e.g. \"Hello, ${/user/name}\"). Do NOT wrap plain static strings in formatString.",
      "oneOf": [
        {
          "type": "string"
        },
        {
          "$ref": "#/$defs/DataBinding"
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/FunctionCall"
            },
            {
              "properties": {
                "returnType": {
                  "const": "string"
                }
              }
            }
          ]
        }
      ]
    },
    "DataBinding": {
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "description": "A JSON Pointer path to a value in the data model."
        }
      },
      "required": [
        "path"
      ],
      "additionalProperties": false
    },
    "FunctionCall": {
      "type": "object",
      "description": "Invokes a named function on the client.",
      "properties": {
        "call": {
          "type": "string",
          "description": "The name of the function to call."
        },
        "args": {
          "description": "Arguments passed to the function.",
          "oneOf": [
            {
              "type": "array",
              "items": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/DynamicValue"
                  },
                  {
                    "type": "object",
                    "description": "A literal object argument (e.g. configuration)."
                  }
                ]
              }
            },
            {
              "type": "object",
              "additionalProperties": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/DynamicValue"
                  },
                  {
                    "type": "object",
                    "description": "A literal object argument (e.g. configuration)."
                  }
                ]
              }
            }
          ]
        },
        "returnType": {
          "type": "string",
          "description": "The expected return type of the function call.",
          "enum": [
            "string",
            "number",
            "boolean",
            "array",
            "object",
            "any",
            "void"
          ],
          "default": "boolean"
        }
      },
      "required": [
        "call"
      ],
      "additionalProperties": false,
      "oneOf": [
        {
          "$ref": "#/$defs/anyFunction"
        }
      ]
    },
    "DynamicValue": {
      "description": "A value of any type. Prefer a plain literal for static values. Use a DataBinding ({\"path\": \"...\"}) to read from the data model. Use a function call when the value must be computed at runtime.",
      "oneOf": [
        {
          "type": "string"
        },
        {
          "type": "number"
        },
        {
          "type": "boolean"
        },
        {
          "type": "array"
        },
        {
          "$ref": "#/$defs/DataBinding"
        },
        {
          "$ref": "#/$defs/FunctionCall"
        }
      ]
    },
    "anyFunction": {
      "oneOf": [
        {
          "$ref": "#/functions/required"
        },
        {
          "$ref": "#/functions/regex"
        },
        {
          "$ref": "#/functions/checkLength"
        },
        {
          "$ref": "#/functions/getLength"
        },
        {
          "$ref": "#/functions/numeric"
        },
        {
          "$ref": "#/functions/email"
        },
        {
          "$ref": "#/functions/formatString"
        },
        {
          "$ref": "#/functions/formatNumber"
        },
        {
          "$ref": "#/functions/formatCurrency"
        },
        {
          "$ref": "#/functions/formatDate"
        },
        {
          "$ref": "#/functions/pluralize"
        },
        {
          "$ref": "#/functions/now"
        },
        {
          "$ref": "#/functions/openUrl"
        },
        {
          "$ref": "#/functions/and"
        },
        {
          "$ref": "#/functions/or"
        },
        {
          "$ref": "#/functions/isEmpty"
        },
        {
          "$ref": "#/functions/eq"
        },
        {
          "$ref": "#/functions/neq"
        },
        {
          "$ref": "#/functions/gt"
        },
        {
          "$ref": "#/functions/gte"
        },
        {
          "$ref": "#/functions/lt"
        },
        {
          "$ref": "#/functions/lte"
        },
        {
          "$ref": "#/functions/show"
        },
        {
          "$ref": "#/functions/hide"
        }
      ]
    },
    "DynamicBoolean": {
      "description": "A boolean value. Prefer a plain literal (true or false) for static values. Use a DataBinding ({\"path\": \"...\"}) to read a boolean from the data model. Use a function call when the value must be computed at runtime (e.g. comparing two data model values).",
      "oneOf": [
        {
          "type": "boolean"
        },
        {
          "$ref": "#/$defs/DataBinding"
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/FunctionCall"
            },
            {
              "properties": {
                "returnType": {
                  "const": "boolean"
                }
              }
            }
          ]
        }
      ]
    },
    "DynamicNumber": {
      "description": "A number value. Prefer a plain number literal for static values (e.g. 300). Use a DataBinding ({\"path\": \"...\"}) to read a number from the data model. Use a function call when the value must be computed at runtime.",
      "oneOf": [
        {
          "type": "number"
        },
        {
          "$ref": "#/$defs/DataBinding"
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/FunctionCall"
            },
            {
              "properties": {
                "returnType": {
                  "const": "number"
                }
              }
            }
          ]
        }
      ]
    },
    "ChildList": {
      "oneOf": [
        {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ComponentId"
          },
          "description": "A static list of child component IDs."
        },
        {
          "type": "object",
          "description": "A template for generating a dynamic list of children from a data model list. The `componentId` is the component to use as a template.",
          "properties": {
            "componentId": {
              "$ref": "#/$defs/ComponentId"
            },
            "path": {
              "type": "string",
              "description": "The path to the list of component property objects in the data model."
            }
          },
          "required": [
            "componentId",
            "path"
          ],
          "additionalProperties": false
        }
      ]
    },
    "Theme": {
      "type": "object",
      "description": "Design token overrides applied as CSS custom properties (--freesail-*) on this component's root element, cascading to all descendants. Accepts CSS color values (hex, rgb, named) or semantic token names.",
      "properties": {
        "bg": {
          "$ref": "#/$defs/DynamicString",
          "description": "Base surface background color."
        },
        "bgRaised": {
          "$ref": "#/$defs/DynamicString",
          "description": "Raised or elevated surface background color."
        },
        "bgMuted": {
          "$ref": "#/$defs/DynamicString",
          "description": "Muted or subdued surface background color."
        },
        "textForeground": {
          "$ref": "#/$defs/DynamicString",
          "description": "Primary text color."
        },
        "textSecondary": {
          "$ref": "#/$defs/DynamicString",
          "description": "Secondary or de-emphasized text color."
        },
        "primary": {
          "$ref": "#/$defs/DynamicString",
          "description": "Brand accent color used for buttons, links, and interactive elements."
        },
        "primaryHover": {
          "$ref": "#/$defs/DynamicString",
          "description": "Brand accent color in hover or focus state."
        },
        "primaryForeground": {
          "$ref": "#/$defs/DynamicString",
          "description": "Text color on primary-colored backgrounds."
        },
        "border": {
          "$ref": "#/$defs/DynamicString",
          "description": "Border and divider color."
        }
      },
      "additionalProperties": false
    },
    "Checkable": {
      "description": "Properties for components that support client-side checks.",
      "type": "object",
      "properties": {
        "checks": {
          "type": "array",
          "description": "A list of checks to perform. These are function calls that must return a boolean indicating validity.",
          "items": {
            "$ref": "#/$defs/CheckRule"
          }
        }
      }
    },
    "CheckRule": {
      "type": "object",
      "description": "A single validation rule applied to an input component.",
      "properties": {
        "condition": {
          "$ref": "#/$defs/DynamicBoolean"
        },
        "message": {
          "type": "string",
          "description": "The error message to display if the check fails."
        }
      },
      "required": [
        "condition",
        "message"
      ],
      "additionalProperties": false
    },
    "Action": {
      "description": "Defines an interaction handler that can either trigger a server-side event or execute a local client-side function.",
      "oneOf": [
        {
          "type": "object",
          "description": "Triggers a server-side event.",
          "properties": {
            "event": {
              "type": "object",
              "description": "The event to dispatch to the server.",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "The name of the action to be dispatched to the server."
                },
                "context": {
                  "type": "object",
                  "description": "A JSON object containing the key-value pairs for the action context. Values can be literals or paths. Use literal values unless the value must be dynamically bound to the data model. Do NOT use paths for static IDs.",
                  "additionalProperties": {
                    "$ref": "#/$defs/DynamicValue"
                  }
                }
              },
              "required": [
                "name"
              ],
              "additionalProperties": false
            }
          },
          "required": [
            "event"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "description": "Executes a local client-side function.",
          "properties": {
            "functionCall": {
              "$ref": "#/$defs/FunctionCall"
            }
          },
          "required": [
            "functionCall"
          ],
          "additionalProperties": false
        }
      ]
    },
    "DynamicStringList": {
      "description": "An array of strings. Prefer a plain literal array for static values (e.g. [\"Option A\", \"Option B\"]). Use a DataBinding ({\"path\": \"...\"}) to read a list from the data model. Use a function call when the list must be computed at runtime.",
      "oneOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "$ref": "#/$defs/DataBinding"
        },
        {
          "allOf": [
            {
              "$ref": "#/$defs/FunctionCall"
            },
            {
              "properties": {
                "returnType": {
                  "const": "array"
                }
              }
            }
          ]
        }
      ]
    },
    "anyComponent": {
      "oneOf": [
        {
          "$ref": "#/components/Text"
        },
        {
          "$ref": "#/components/Icon"
        },
        {
          "$ref": "#/components/Row"
        },
        {
          "$ref": "#/components/Column"
        },
        {
          "$ref": "#/components/Card"
        },
        {
          "$ref": "#/components/Modal"
        },
        {
          "$ref": "#/components/Button"
        },
        {
          "$ref": "#/components/TextField"
        },
        {
          "$ref": "#/components/ChoicePickerSingleSelect"
        },
        {
          "$ref": "#/components/ChoicePickerMultiSelect"
        },
        {
          "$ref": "#/components/DateInput"
        },
        {
          "$ref": "#/components/TimeInput"
        },
        {
          "$ref": "#/components/Spacer"
        },
        {
          "$ref": "#/components/Image"
        },
        {
          "$ref": "#/components/Video"
        },
        {
          "$ref": "#/components/AudioPlayer"
        },
        {
          "$ref": "#/components/List"
        },
        {
          "$ref": "#/components/TabGroup"
        },
        {
          "$ref": "#/components/Tab"
        },
        {
          "$ref": "#/components/Divider"
        },
        {
          "$ref": "#/components/Dropdown"
        },
        {
          "$ref": "#/components/CheckBox"
        },
        {
          "$ref": "#/components/Slider"
        },
        {
          "$ref": "#/components/FluidGrid"
        },
        {
          "$ref": "#/components/TabularGrid"
        },
        {
          "$ref": "#/components/BarChart"
        },
        {
          "$ref": "#/components/LineChart"
        },
        {
          "$ref": "#/components/PieChart"
        },
        {
          "$ref": "#/components/Sparkline"
        },
        {
          "$ref": "#/components/StatCard"
        }
      ],
      "discriminator": {
        "propertyName": "component"
      }
    }
  }
}
