feat(viz-platform): implement DMC 2.x component registry (#171)
- Add component_registry.py with version-locked registry loading - Create dmc_2_5.json with 39 components for DMC 2.5.1/Mantine 7 - Add generate-dmc-registry.py script for future registry generation - Update dependencies to DMC >=2.0.0 (installs 2.5.1) - Includes prop validation with typo detection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
301
mcp-servers/viz-platform/mcp_server/component_registry.py
Normal file
301
mcp-servers/viz-platform/mcp_server/component_registry.py
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
"""
|
||||||
|
DMC Component Registry for viz-platform.
|
||||||
|
|
||||||
|
Provides version-locked component definitions to prevent Claude from
|
||||||
|
hallucinating invalid props. Uses static JSON registries pre-generated
|
||||||
|
from DMC source.
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, List, Optional, Any
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ComponentRegistry:
|
||||||
|
"""
|
||||||
|
Version-locked registry of Dash Mantine Components.
|
||||||
|
|
||||||
|
Loads component definitions from static JSON files and provides
|
||||||
|
lookup methods for validation tools.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, dmc_version: Optional[str] = None):
|
||||||
|
"""
|
||||||
|
Initialize the component registry.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dmc_version: Installed DMC version (e.g., "0.14.7").
|
||||||
|
If None, will try to detect or use fallback.
|
||||||
|
"""
|
||||||
|
self.dmc_version = dmc_version
|
||||||
|
self.registry_dir = Path(__file__).parent.parent / 'registry'
|
||||||
|
self.components: Dict[str, Dict[str, Any]] = {}
|
||||||
|
self.categories: Dict[str, List[str]] = {}
|
||||||
|
self.loaded_version: Optional[str] = None
|
||||||
|
|
||||||
|
def load(self) -> bool:
|
||||||
|
"""
|
||||||
|
Load the component registry for the configured DMC version.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if registry loaded successfully, False otherwise
|
||||||
|
"""
|
||||||
|
registry_file = self._find_registry_file()
|
||||||
|
|
||||||
|
if not registry_file:
|
||||||
|
logger.warning(
|
||||||
|
f"No registry found for DMC {self.dmc_version}. "
|
||||||
|
"Component validation will be limited."
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(registry_file, 'r') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
self.loaded_version = data.get('version')
|
||||||
|
self.components = data.get('components', {})
|
||||||
|
self.categories = data.get('categories', {})
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"Loaded component registry v{self.loaded_version} "
|
||||||
|
f"with {len(self.components)} components"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to load registry: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _find_registry_file(self) -> Optional[Path]:
|
||||||
|
"""
|
||||||
|
Find the best matching registry file for the DMC version.
|
||||||
|
|
||||||
|
Strategy:
|
||||||
|
1. Exact major.minor match (e.g., dmc_0_14.json for 0.14.7)
|
||||||
|
2. Fallback to latest available registry
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Path to registry file, or None if not found
|
||||||
|
"""
|
||||||
|
if not self.registry_dir.exists():
|
||||||
|
logger.warning(f"Registry directory not found: {self.registry_dir}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Try exact major.minor match
|
||||||
|
if self.dmc_version:
|
||||||
|
parts = self.dmc_version.split('.')
|
||||||
|
if len(parts) >= 2:
|
||||||
|
major_minor = f"{parts[0]}_{parts[1]}"
|
||||||
|
exact_match = self.registry_dir / f"dmc_{major_minor}.json"
|
||||||
|
if exact_match.exists():
|
||||||
|
return exact_match
|
||||||
|
|
||||||
|
# Fallback: find latest registry
|
||||||
|
registry_files = list(self.registry_dir.glob("dmc_*.json"))
|
||||||
|
if registry_files:
|
||||||
|
# Sort by version and return latest
|
||||||
|
registry_files.sort(reverse=True)
|
||||||
|
fallback = registry_files[0]
|
||||||
|
if self.dmc_version:
|
||||||
|
logger.warning(
|
||||||
|
f"No exact match for DMC {self.dmc_version}, "
|
||||||
|
f"using fallback: {fallback.name}"
|
||||||
|
)
|
||||||
|
return fallback
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_component(self, name: str) -> Optional[Dict[str, Any]]:
|
||||||
|
"""
|
||||||
|
Get component definition by name.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Component name (e.g., "Button", "TextInput")
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Component definition dict, or None if not found
|
||||||
|
"""
|
||||||
|
return self.components.get(name)
|
||||||
|
|
||||||
|
def get_component_props(self, name: str) -> Optional[Dict[str, Any]]:
|
||||||
|
"""
|
||||||
|
Get props schema for a component.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Component name
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Props dict with type info, or None if component not found
|
||||||
|
"""
|
||||||
|
component = self.get_component(name)
|
||||||
|
if component:
|
||||||
|
return component.get('props', {})
|
||||||
|
return None
|
||||||
|
|
||||||
|
def list_components(self, category: Optional[str] = None) -> Dict[str, List[str]]:
|
||||||
|
"""
|
||||||
|
List available components, optionally filtered by category.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
category: Optional category filter (e.g., "inputs", "buttons")
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict of category -> component names
|
||||||
|
"""
|
||||||
|
if category:
|
||||||
|
if category in self.categories:
|
||||||
|
return {category: self.categories[category]}
|
||||||
|
return {}
|
||||||
|
return self.categories
|
||||||
|
|
||||||
|
def get_categories(self) -> List[str]:
|
||||||
|
"""
|
||||||
|
Get list of available component categories.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of category names
|
||||||
|
"""
|
||||||
|
return list(self.categories.keys())
|
||||||
|
|
||||||
|
def validate_prop(
|
||||||
|
self,
|
||||||
|
component: str,
|
||||||
|
prop_name: str,
|
||||||
|
prop_value: Any
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Validate a single prop value against the registry.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
component: Component name
|
||||||
|
prop_name: Prop name
|
||||||
|
prop_value: Value to validate
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict with valid: bool, error: Optional[str]
|
||||||
|
"""
|
||||||
|
props = self.get_component_props(component)
|
||||||
|
if props is None:
|
||||||
|
return {
|
||||||
|
'valid': False,
|
||||||
|
'error': f"Unknown component: {component}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if prop_name not in props:
|
||||||
|
# Check for similar prop names (typo detection)
|
||||||
|
similar = self._find_similar_props(prop_name, props.keys())
|
||||||
|
if similar:
|
||||||
|
return {
|
||||||
|
'valid': False,
|
||||||
|
'error': f"Unknown prop '{prop_name}' for {component}. Did you mean '{similar}'?"
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
'valid': False,
|
||||||
|
'error': f"Unknown prop '{prop_name}' for {component}"
|
||||||
|
}
|
||||||
|
|
||||||
|
prop_schema = props[prop_name]
|
||||||
|
return self._validate_value(prop_value, prop_schema, prop_name)
|
||||||
|
|
||||||
|
def _validate_value(
|
||||||
|
self,
|
||||||
|
value: Any,
|
||||||
|
schema: Dict[str, Any],
|
||||||
|
prop_name: str
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Validate a value against a prop schema.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: Value to validate
|
||||||
|
schema: Prop schema from registry
|
||||||
|
prop_name: Prop name (for error messages)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict with valid: bool, error: Optional[str]
|
||||||
|
"""
|
||||||
|
prop_type = schema.get('type', 'any')
|
||||||
|
|
||||||
|
# Any type always valid
|
||||||
|
if prop_type == 'any':
|
||||||
|
return {'valid': True}
|
||||||
|
|
||||||
|
# Check enum values
|
||||||
|
if 'enum' in schema:
|
||||||
|
if value not in schema['enum']:
|
||||||
|
return {
|
||||||
|
'valid': False,
|
||||||
|
'error': f"Prop '{prop_name}' expects one of {schema['enum']}, got '{value}'"
|
||||||
|
}
|
||||||
|
return {'valid': True}
|
||||||
|
|
||||||
|
# Type checking
|
||||||
|
type_checks = {
|
||||||
|
'string': lambda v: isinstance(v, str),
|
||||||
|
'number': lambda v: isinstance(v, (int, float)),
|
||||||
|
'integer': lambda v: isinstance(v, int),
|
||||||
|
'boolean': lambda v: isinstance(v, bool),
|
||||||
|
'array': lambda v: isinstance(v, list),
|
||||||
|
'object': lambda v: isinstance(v, dict),
|
||||||
|
}
|
||||||
|
|
||||||
|
checker = type_checks.get(prop_type)
|
||||||
|
if checker and not checker(value):
|
||||||
|
return {
|
||||||
|
'valid': False,
|
||||||
|
'error': f"Prop '{prop_name}' expects type '{prop_type}', got '{type(value).__name__}'"
|
||||||
|
}
|
||||||
|
|
||||||
|
return {'valid': True}
|
||||||
|
|
||||||
|
def _find_similar_props(
|
||||||
|
self,
|
||||||
|
prop_name: str,
|
||||||
|
available_props: List[str]
|
||||||
|
) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Find a similar prop name for typo suggestions.
|
||||||
|
|
||||||
|
Uses simple edit distance heuristic.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prop_name: The (possibly misspelled) prop name
|
||||||
|
available_props: List of valid prop names
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Most similar prop name, or None if no close match
|
||||||
|
"""
|
||||||
|
prop_lower = prop_name.lower()
|
||||||
|
|
||||||
|
for prop in available_props:
|
||||||
|
# Exact match after lowercase
|
||||||
|
if prop.lower() == prop_lower:
|
||||||
|
return prop
|
||||||
|
# Common typos: extra/missing letter
|
||||||
|
if abs(len(prop) - len(prop_name)) == 1:
|
||||||
|
if prop_lower.startswith(prop.lower()[:3]):
|
||||||
|
return prop
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_loaded(self) -> bool:
|
||||||
|
"""Check if registry is loaded."""
|
||||||
|
return len(self.components) > 0
|
||||||
|
|
||||||
|
|
||||||
|
def load_registry(dmc_version: Optional[str] = None) -> ComponentRegistry:
|
||||||
|
"""
|
||||||
|
Convenience function to load and return a component registry.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dmc_version: Optional DMC version string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Loaded ComponentRegistry instance
|
||||||
|
"""
|
||||||
|
registry = ComponentRegistry(dmc_version)
|
||||||
|
registry.load()
|
||||||
|
return registry
|
||||||
@@ -25,7 +25,7 @@ dependencies = [
|
|||||||
"mcp>=0.9.0",
|
"mcp>=0.9.0",
|
||||||
"plotly>=5.18.0",
|
"plotly>=5.18.0",
|
||||||
"dash>=2.14.0",
|
"dash>=2.14.0",
|
||||||
"dash-mantine-components>=0.14.0",
|
"dash-mantine-components>=2.0.0",
|
||||||
"python-dotenv>=1.0.0",
|
"python-dotenv>=1.0.0",
|
||||||
"pydantic>=2.5.0",
|
"pydantic>=2.5.0",
|
||||||
]
|
]
|
||||||
|
|||||||
668
mcp-servers/viz-platform/registry/dmc_2_5.json
Normal file
668
mcp-servers/viz-platform/registry/dmc_2_5.json
Normal file
@@ -0,0 +1,668 @@
|
|||||||
|
{
|
||||||
|
"version": "2.5.1",
|
||||||
|
"generated": "2026-01-26",
|
||||||
|
"mantine_version": "7.x",
|
||||||
|
"categories": {
|
||||||
|
"buttons": ["Button", "ButtonGroup", "ActionIcon", "ActionIconGroup", "CopyButton", "CloseButton", "UnstyledButton"],
|
||||||
|
"inputs": [
|
||||||
|
"TextInput", "PasswordInput", "NumberInput", "Textarea", "Select", "MultiSelect",
|
||||||
|
"Checkbox", "CheckboxGroup", "CheckboxCard", "Switch", "Radio", "RadioGroup", "RadioCard",
|
||||||
|
"Slider", "RangeSlider", "ColorInput", "ColorPicker", "Autocomplete", "TagsInput",
|
||||||
|
"PinInput", "Rating", "SegmentedControl", "Chip", "ChipGroup", "JsonInput",
|
||||||
|
"NativeSelect", "FileInput", "Combobox"
|
||||||
|
],
|
||||||
|
"navigation": ["Anchor", "Breadcrumbs", "Burger", "NavLink", "Pagination", "Stepper", "Tabs", "TabsList", "TabsTab", "TabsPanel"],
|
||||||
|
"feedback": ["Alert", "Loader", "Notification", "NotificationContainer", "Progress", "RingProgress", "Skeleton"],
|
||||||
|
"overlays": ["Modal", "Drawer", "DrawerStack", "Popover", "HoverCard", "Tooltip", "FloatingTooltip", "Menu", "MenuTarget", "MenuDropdown", "MenuItem", "Affix"],
|
||||||
|
"typography": ["Text", "Title", "Highlight", "Mark", "Code", "CodeHighlight", "Blockquote", "List", "ListItem", "Kbd"],
|
||||||
|
"layout": [
|
||||||
|
"AppShell", "AppShellHeader", "AppShellNavbar", "AppShellAside", "AppShellFooter", "AppShellMain", "AppShellSection",
|
||||||
|
"Container", "Center", "Stack", "Group", "Flex", "Grid", "GridCol", "SimpleGrid",
|
||||||
|
"Paper", "Card", "CardSection", "Box", "Space", "Divider", "AspectRatio", "ScrollArea"
|
||||||
|
],
|
||||||
|
"data_display": [
|
||||||
|
"Accordion", "AccordionItem", "AccordionControl", "AccordionPanel",
|
||||||
|
"Avatar", "AvatarGroup", "Badge", "Image", "BackgroundImage",
|
||||||
|
"Indicator", "Spoiler", "Table", "ThemeIcon", "Timeline", "TimelineItem", "Tree"
|
||||||
|
],
|
||||||
|
"charts": ["AreaChart", "BarChart", "LineChart", "PieChart", "DonutChart", "RadarChart", "ScatterChart", "BubbleChart", "CompositeChart", "Sparkline"],
|
||||||
|
"dates": ["DatePicker", "DateTimePicker", "DateInput", "DatePickerInput", "MonthPicker", "YearPicker", "TimePicker", "TimeInput", "Calendar", "MiniCalendar", "DatesProvider"]
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"Button": {
|
||||||
|
"description": "Button component for user interactions",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any", "description": "Button content"},
|
||||||
|
"variant": {"type": "string", "enum": ["filled", "light", "outline", "transparent", "white", "subtle", "default", "gradient"], "default": "filled"},
|
||||||
|
"color": {"type": "string", "default": "blue", "description": "Key of theme.colors or CSS color"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl", "compact-xs", "compact-sm", "compact-md", "compact-lg", "compact-xl"], "default": "sm"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"loading": {"type": "boolean", "default": false},
|
||||||
|
"loaderProps": {"type": "object"},
|
||||||
|
"leftSection": {"type": "any", "description": "Content on the left side of label"},
|
||||||
|
"rightSection": {"type": "any", "description": "Content on the right side of label"},
|
||||||
|
"fullWidth": {"type": "boolean", "default": false},
|
||||||
|
"gradient": {"type": "object", "description": "Gradient for gradient variant"},
|
||||||
|
"justify": {"type": "string", "enum": ["center", "start", "end", "space-between"], "default": "center"},
|
||||||
|
"autoContrast": {"type": "boolean", "default": false},
|
||||||
|
"n_clicks": {"type": "integer", "default": 0, "description": "Dash callback trigger"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ActionIcon": {
|
||||||
|
"description": "Icon button without text label",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any", "required": true, "description": "Icon element"},
|
||||||
|
"variant": {"type": "string", "enum": ["filled", "light", "outline", "transparent", "white", "subtle", "default", "gradient"], "default": "subtle"},
|
||||||
|
"color": {"type": "string", "default": "gray"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"loading": {"type": "boolean", "default": false},
|
||||||
|
"autoContrast": {"type": "boolean", "default": false},
|
||||||
|
"n_clicks": {"type": "integer", "default": 0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TextInput": {
|
||||||
|
"description": "Text input field",
|
||||||
|
"props": {
|
||||||
|
"value": {"type": "string", "default": ""},
|
||||||
|
"placeholder": {"type": "string"},
|
||||||
|
"label": {"type": "any"},
|
||||||
|
"description": {"type": "any"},
|
||||||
|
"error": {"type": "any"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"required": {"type": "boolean", "default": false},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"variant": {"type": "string", "enum": ["default", "filled", "unstyled"], "default": "default"},
|
||||||
|
"leftSection": {"type": "any"},
|
||||||
|
"rightSection": {"type": "any"},
|
||||||
|
"withAsterisk": {"type": "boolean", "default": false},
|
||||||
|
"debounce": {"type": "integer", "description": "Debounce delay in ms"},
|
||||||
|
"leftSectionPointerEvents": {"type": "string", "enum": ["none", "all"], "default": "none"},
|
||||||
|
"rightSectionPointerEvents": {"type": "string", "enum": ["none", "all"], "default": "none"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NumberInput": {
|
||||||
|
"description": "Numeric input with optional controls",
|
||||||
|
"props": {
|
||||||
|
"value": {"type": "number"},
|
||||||
|
"placeholder": {"type": "string"},
|
||||||
|
"label": {"type": "any"},
|
||||||
|
"description": {"type": "any"},
|
||||||
|
"error": {"type": "any"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"required": {"type": "boolean", "default": false},
|
||||||
|
"min": {"type": "number"},
|
||||||
|
"max": {"type": "number"},
|
||||||
|
"step": {"type": "number", "default": 1},
|
||||||
|
"hideControls": {"type": "boolean", "default": false},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"allowNegative": {"type": "boolean", "default": true},
|
||||||
|
"allowDecimal": {"type": "boolean", "default": true},
|
||||||
|
"clampBehavior": {"type": "string", "enum": ["strict", "blur", "none"], "default": "blur"},
|
||||||
|
"decimalScale": {"type": "integer"},
|
||||||
|
"fixedDecimalScale": {"type": "boolean", "default": false},
|
||||||
|
"thousandSeparator": {"type": "string"},
|
||||||
|
"decimalSeparator": {"type": "string"},
|
||||||
|
"prefix": {"type": "string"},
|
||||||
|
"suffix": {"type": "string"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Select": {
|
||||||
|
"description": "Dropdown select input",
|
||||||
|
"props": {
|
||||||
|
"value": {"type": "string"},
|
||||||
|
"data": {"type": "array", "required": true, "description": "Array of options: strings or {value, label} objects"},
|
||||||
|
"placeholder": {"type": "string"},
|
||||||
|
"label": {"type": "any"},
|
||||||
|
"description": {"type": "any"},
|
||||||
|
"error": {"type": "any"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"required": {"type": "boolean", "default": false},
|
||||||
|
"searchable": {"type": "boolean", "default": false},
|
||||||
|
"clearable": {"type": "boolean", "default": false},
|
||||||
|
"nothingFoundMessage": {"type": "string"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"maxDropdownHeight": {"type": "number", "default": 250},
|
||||||
|
"allowDeselect": {"type": "boolean", "default": true},
|
||||||
|
"checkIconPosition": {"type": "string", "enum": ["left", "right"], "default": "left"},
|
||||||
|
"comboboxProps": {"type": "object"},
|
||||||
|
"withScrollArea": {"type": "boolean", "default": true}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MultiSelect": {
|
||||||
|
"description": "Multiple selection dropdown",
|
||||||
|
"props": {
|
||||||
|
"value": {"type": "array", "default": []},
|
||||||
|
"data": {"type": "array", "required": true},
|
||||||
|
"placeholder": {"type": "string"},
|
||||||
|
"label": {"type": "any"},
|
||||||
|
"description": {"type": "any"},
|
||||||
|
"error": {"type": "any"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"required": {"type": "boolean", "default": false},
|
||||||
|
"searchable": {"type": "boolean", "default": false},
|
||||||
|
"clearable": {"type": "boolean", "default": false},
|
||||||
|
"maxValues": {"type": "integer"},
|
||||||
|
"hidePickedOptions": {"type": "boolean", "default": false},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"maxDropdownHeight": {"type": "number", "default": 250},
|
||||||
|
"withCheckIcon": {"type": "boolean", "default": true}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Checkbox": {
|
||||||
|
"description": "Checkbox input",
|
||||||
|
"props": {
|
||||||
|
"checked": {"type": "boolean", "default": false},
|
||||||
|
"label": {"type": "any"},
|
||||||
|
"description": {"type": "any"},
|
||||||
|
"error": {"type": "any"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"indeterminate": {"type": "boolean", "default": false},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"color": {"type": "string", "default": "blue"},
|
||||||
|
"labelPosition": {"type": "string", "enum": ["left", "right"], "default": "right"},
|
||||||
|
"autoContrast": {"type": "boolean", "default": false},
|
||||||
|
"icon": {"type": "any"},
|
||||||
|
"iconColor": {"type": "string"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Switch": {
|
||||||
|
"description": "Toggle switch input",
|
||||||
|
"props": {
|
||||||
|
"checked": {"type": "boolean", "default": false},
|
||||||
|
"label": {"type": "any"},
|
||||||
|
"description": {"type": "any"},
|
||||||
|
"error": {"type": "any"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "xl"},
|
||||||
|
"color": {"type": "string", "default": "blue"},
|
||||||
|
"onLabel": {"type": "any"},
|
||||||
|
"offLabel": {"type": "any"},
|
||||||
|
"thumbIcon": {"type": "any"},
|
||||||
|
"labelPosition": {"type": "string", "enum": ["left", "right"], "default": "right"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Slider": {
|
||||||
|
"description": "Slider input for numeric values",
|
||||||
|
"props": {
|
||||||
|
"value": {"type": "number"},
|
||||||
|
"min": {"type": "number", "default": 0},
|
||||||
|
"max": {"type": "number", "default": 100},
|
||||||
|
"step": {"type": "number", "default": 1},
|
||||||
|
"label": {"type": "any"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"marks": {"type": "array"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "xl"},
|
||||||
|
"color": {"type": "string", "default": "blue"},
|
||||||
|
"showLabelOnHover": {"type": "boolean", "default": true},
|
||||||
|
"labelAlwaysOn": {"type": "boolean", "default": false},
|
||||||
|
"thumbLabel": {"type": "string"},
|
||||||
|
"precision": {"type": "integer", "default": 0},
|
||||||
|
"inverted": {"type": "boolean", "default": false},
|
||||||
|
"thumbSize": {"type": "number"},
|
||||||
|
"restrictToMarks": {"type": "boolean", "default": false}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Alert": {
|
||||||
|
"description": "Alert component for feedback messages",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"title": {"type": "any"},
|
||||||
|
"color": {"type": "string", "default": "blue"},
|
||||||
|
"variant": {"type": "string", "enum": ["filled", "light", "outline", "default", "transparent", "white"], "default": "light"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"icon": {"type": "any"},
|
||||||
|
"withCloseButton": {"type": "boolean", "default": false},
|
||||||
|
"closeButtonLabel": {"type": "string"},
|
||||||
|
"autoContrast": {"type": "boolean", "default": false}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Loader": {
|
||||||
|
"description": "Loading indicator",
|
||||||
|
"props": {
|
||||||
|
"color": {"type": "string", "default": "blue"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"type": {"type": "string", "enum": ["oval", "bars", "dots"], "default": "oval"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Progress": {
|
||||||
|
"description": "Progress bar",
|
||||||
|
"props": {
|
||||||
|
"value": {"type": "number", "required": true},
|
||||||
|
"color": {"type": "string", "default": "blue"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"striped": {"type": "boolean", "default": false},
|
||||||
|
"animated": {"type": "boolean", "default": false},
|
||||||
|
"autoContrast": {"type": "boolean", "default": false},
|
||||||
|
"transitionDuration": {"type": "number", "default": 100}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Modal": {
|
||||||
|
"description": "Modal dialog overlay",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"opened": {"type": "boolean", "required": true},
|
||||||
|
"title": {"type": "any"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl", "auto"], "default": "md"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"centered": {"type": "boolean", "default": false},
|
||||||
|
"fullScreen": {"type": "boolean", "default": false},
|
||||||
|
"withCloseButton": {"type": "boolean", "default": true},
|
||||||
|
"closeOnClickOutside": {"type": "boolean", "default": true},
|
||||||
|
"closeOnEscape": {"type": "boolean", "default": true},
|
||||||
|
"overlayProps": {"type": "object"},
|
||||||
|
"padding": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"transitionProps": {"type": "object"},
|
||||||
|
"zIndex": {"type": "number", "default": 200},
|
||||||
|
"trapFocus": {"type": "boolean", "default": true},
|
||||||
|
"returnFocus": {"type": "boolean", "default": true},
|
||||||
|
"lockScroll": {"type": "boolean", "default": true}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Drawer": {
|
||||||
|
"description": "Sliding panel drawer",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"opened": {"type": "boolean", "required": true},
|
||||||
|
"title": {"type": "any"},
|
||||||
|
"position": {"type": "string", "enum": ["left", "right", "top", "bottom"], "default": "left"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"]},
|
||||||
|
"withCloseButton": {"type": "boolean", "default": true},
|
||||||
|
"closeOnClickOutside": {"type": "boolean", "default": true},
|
||||||
|
"closeOnEscape": {"type": "boolean", "default": true},
|
||||||
|
"overlayProps": {"type": "object"},
|
||||||
|
"padding": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"zIndex": {"type": "number", "default": 200},
|
||||||
|
"offset": {"type": "number", "default": 0},
|
||||||
|
"trapFocus": {"type": "boolean", "default": true},
|
||||||
|
"returnFocus": {"type": "boolean", "default": true},
|
||||||
|
"lockScroll": {"type": "boolean", "default": true}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Tooltip": {
|
||||||
|
"description": "Tooltip on hover",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any", "required": true},
|
||||||
|
"label": {"type": "any", "required": true},
|
||||||
|
"position": {"type": "string", "enum": ["top", "right", "bottom", "left", "top-start", "top-end", "right-start", "right-end", "bottom-start", "bottom-end", "left-start", "left-end"], "default": "top"},
|
||||||
|
"color": {"type": "string"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"withArrow": {"type": "boolean", "default": false},
|
||||||
|
"arrowSize": {"type": "number", "default": 4},
|
||||||
|
"arrowOffset": {"type": "number", "default": 5},
|
||||||
|
"offset": {"type": "number", "default": 5},
|
||||||
|
"multiline": {"type": "boolean", "default": false},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"openDelay": {"type": "number", "default": 0},
|
||||||
|
"closeDelay": {"type": "number", "default": 0},
|
||||||
|
"transitionProps": {"type": "object"},
|
||||||
|
"zIndex": {"type": "number", "default": 300}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Text": {
|
||||||
|
"description": "Text component with styling",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"]},
|
||||||
|
"c": {"type": "string", "description": "Color"},
|
||||||
|
"fw": {"type": "number", "description": "Font weight"},
|
||||||
|
"fs": {"type": "string", "enum": ["normal", "italic"], "description": "Font style"},
|
||||||
|
"td": {"type": "string", "enum": ["none", "underline", "line-through"], "description": "Text decoration"},
|
||||||
|
"tt": {"type": "string", "enum": ["none", "capitalize", "uppercase", "lowercase"], "description": "Text transform"},
|
||||||
|
"ta": {"type": "string", "enum": ["left", "center", "right", "justify"], "description": "Text align"},
|
||||||
|
"lineClamp": {"type": "integer"},
|
||||||
|
"truncate": {"type": "boolean", "default": false},
|
||||||
|
"inherit": {"type": "boolean", "default": false},
|
||||||
|
"gradient": {"type": "object"},
|
||||||
|
"span": {"type": "boolean", "default": false},
|
||||||
|
"lh": {"type": "string", "description": "Line height"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Title": {
|
||||||
|
"description": "Heading component",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"order": {"type": "integer", "enum": [1, 2, 3, 4, 5, 6], "default": 1},
|
||||||
|
"size": {"type": "string"},
|
||||||
|
"c": {"type": "string", "description": "Color"},
|
||||||
|
"ta": {"type": "string", "enum": ["left", "center", "right", "justify"]},
|
||||||
|
"td": {"type": "string", "enum": ["none", "underline", "line-through"]},
|
||||||
|
"tt": {"type": "string", "enum": ["none", "capitalize", "uppercase", "lowercase"]},
|
||||||
|
"lineClamp": {"type": "integer"},
|
||||||
|
"truncate": {"type": "boolean", "default": false}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Stack": {
|
||||||
|
"description": "Vertical stack layout",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"gap": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"align": {"type": "string", "enum": ["stretch", "center", "flex-start", "flex-end"], "default": "stretch"},
|
||||||
|
"justify": {"type": "string", "enum": ["flex-start", "flex-end", "center", "space-between", "space-around", "space-evenly"], "default": "flex-start"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Group": {
|
||||||
|
"description": "Horizontal group layout",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"gap": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"align": {"type": "string", "enum": ["stretch", "center", "flex-start", "flex-end"], "default": "center"},
|
||||||
|
"justify": {"type": "string", "enum": ["flex-start", "flex-end", "center", "space-between", "space-around"], "default": "flex-start"},
|
||||||
|
"grow": {"type": "boolean", "default": false},
|
||||||
|
"wrap": {"type": "string", "enum": ["wrap", "nowrap", "wrap-reverse"], "default": "wrap"},
|
||||||
|
"preventGrowOverflow": {"type": "boolean", "default": true}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Flex": {
|
||||||
|
"description": "Flexbox container",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"gap": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"]},
|
||||||
|
"rowGap": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"]},
|
||||||
|
"columnGap": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"]},
|
||||||
|
"align": {"type": "string", "enum": ["stretch", "center", "flex-start", "flex-end", "baseline"]},
|
||||||
|
"justify": {"type": "string", "enum": ["flex-start", "flex-end", "center", "space-between", "space-around", "space-evenly"]},
|
||||||
|
"wrap": {"type": "string", "enum": ["wrap", "nowrap", "wrap-reverse"], "default": "nowrap"},
|
||||||
|
"direction": {"type": "string", "enum": ["row", "column", "row-reverse", "column-reverse"], "default": "row"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Grid": {
|
||||||
|
"description": "Grid layout component",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"columns": {"type": "integer", "default": 12},
|
||||||
|
"gutter": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"grow": {"type": "boolean", "default": false},
|
||||||
|
"justify": {"type": "string", "enum": ["flex-start", "flex-end", "center", "space-between", "space-around"], "default": "flex-start"},
|
||||||
|
"align": {"type": "string", "enum": ["stretch", "center", "flex-start", "flex-end"], "default": "stretch"},
|
||||||
|
"overflow": {"type": "string", "enum": ["visible", "hidden"], "default": "visible"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SimpleGrid": {
|
||||||
|
"description": "Simple grid with equal columns",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"cols": {"type": "integer", "default": 1},
|
||||||
|
"spacing": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"verticalSpacing": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"]}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Container": {
|
||||||
|
"description": "Centered container with max-width",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"fluid": {"type": "boolean", "default": false}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Paper": {
|
||||||
|
"description": "Paper surface component",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"shadow": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"]},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"p": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "description": "Padding"},
|
||||||
|
"withBorder": {"type": "boolean", "default": false}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Card": {
|
||||||
|
"description": "Card container",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"shadow": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"padding": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"withBorder": {"type": "boolean", "default": false}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Tabs": {
|
||||||
|
"description": "Tabbed interface",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"value": {"type": "string"},
|
||||||
|
"defaultValue": {"type": "string"},
|
||||||
|
"orientation": {"type": "string", "enum": ["horizontal", "vertical"], "default": "horizontal"},
|
||||||
|
"variant": {"type": "string", "enum": ["default", "outline", "pills"], "default": "default"},
|
||||||
|
"color": {"type": "string", "default": "blue"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"placement": {"type": "string", "enum": ["left", "right"], "default": "left"},
|
||||||
|
"grow": {"type": "boolean", "default": false},
|
||||||
|
"inverted": {"type": "boolean", "default": false},
|
||||||
|
"keepMounted": {"type": "boolean", "default": true},
|
||||||
|
"activateTabWithKeyboard": {"type": "boolean", "default": true},
|
||||||
|
"allowTabDeactivation": {"type": "boolean", "default": false},
|
||||||
|
"autoContrast": {"type": "boolean", "default": false}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Accordion": {
|
||||||
|
"description": "Collapsible content panels",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"value": {"type": "any"},
|
||||||
|
"defaultValue": {"type": "any"},
|
||||||
|
"multiple": {"type": "boolean", "default": false},
|
||||||
|
"variant": {"type": "string", "enum": ["default", "contained", "filled", "separated"], "default": "default"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"chevronPosition": {"type": "string", "enum": ["left", "right"], "default": "right"},
|
||||||
|
"disableChevronRotation": {"type": "boolean", "default": false},
|
||||||
|
"transitionDuration": {"type": "number", "default": 200},
|
||||||
|
"chevronSize": {"type": "any"},
|
||||||
|
"order": {"type": "integer", "enum": [2, 3, 4, 5, 6]}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Badge": {
|
||||||
|
"description": "Badge for status or labels",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"color": {"type": "string", "default": "blue"},
|
||||||
|
"variant": {"type": "string", "enum": ["filled", "light", "outline", "dot", "gradient", "default", "transparent", "white"], "default": "filled"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "xl"},
|
||||||
|
"fullWidth": {"type": "boolean", "default": false},
|
||||||
|
"leftSection": {"type": "any"},
|
||||||
|
"rightSection": {"type": "any"},
|
||||||
|
"autoContrast": {"type": "boolean", "default": false},
|
||||||
|
"circle": {"type": "boolean", "default": false}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Avatar": {
|
||||||
|
"description": "User avatar image",
|
||||||
|
"props": {
|
||||||
|
"src": {"type": "string"},
|
||||||
|
"alt": {"type": "string"},
|
||||||
|
"children": {"type": "any", "description": "Fallback content"},
|
||||||
|
"color": {"type": "string", "default": "gray"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "md"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "xl"},
|
||||||
|
"variant": {"type": "string", "enum": ["filled", "light", "outline", "gradient", "default", "transparent", "white"], "default": "filled"},
|
||||||
|
"autoContrast": {"type": "boolean", "default": false}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Image": {
|
||||||
|
"description": "Image with fallback",
|
||||||
|
"props": {
|
||||||
|
"src": {"type": "string"},
|
||||||
|
"alt": {"type": "string"},
|
||||||
|
"w": {"type": "any", "description": "Width"},
|
||||||
|
"h": {"type": "any", "description": "Height"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"]},
|
||||||
|
"fit": {"type": "string", "enum": ["contain", "cover", "fill", "none", "scale-down"], "default": "cover"},
|
||||||
|
"fallbackSrc": {"type": "string"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Table": {
|
||||||
|
"description": "Data table component",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any"},
|
||||||
|
"data": {"type": "object", "description": "Table data object with head, body, foot"},
|
||||||
|
"striped": {"type": "boolean", "default": false},
|
||||||
|
"highlightOnHover": {"type": "boolean", "default": false},
|
||||||
|
"withTableBorder": {"type": "boolean", "default": false},
|
||||||
|
"withColumnBorders": {"type": "boolean", "default": false},
|
||||||
|
"withRowBorders": {"type": "boolean", "default": true},
|
||||||
|
"verticalSpacing": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "xs"},
|
||||||
|
"horizontalSpacing": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "xs"},
|
||||||
|
"captionSide": {"type": "string", "enum": ["top", "bottom"], "default": "bottom"},
|
||||||
|
"stickyHeader": {"type": "boolean", "default": false},
|
||||||
|
"stickyHeaderOffset": {"type": "number", "default": 0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AreaChart": {
|
||||||
|
"description": "Area chart for time series data",
|
||||||
|
"props": {
|
||||||
|
"data": {"type": "array", "required": true},
|
||||||
|
"dataKey": {"type": "string", "required": true, "description": "X-axis data key"},
|
||||||
|
"series": {"type": "array", "required": true, "description": "Array of {name, color} objects"},
|
||||||
|
"h": {"type": "any", "description": "Chart height"},
|
||||||
|
"w": {"type": "any", "description": "Chart width"},
|
||||||
|
"curveType": {"type": "string", "enum": ["bump", "linear", "natural", "monotone", "step", "stepBefore", "stepAfter"], "default": "monotone"},
|
||||||
|
"connectNulls": {"type": "boolean", "default": true},
|
||||||
|
"withDots": {"type": "boolean", "default": true},
|
||||||
|
"withGradient": {"type": "boolean", "default": true},
|
||||||
|
"withLegend": {"type": "boolean", "default": false},
|
||||||
|
"withTooltip": {"type": "boolean", "default": true},
|
||||||
|
"withXAxis": {"type": "boolean", "default": true},
|
||||||
|
"withYAxis": {"type": "boolean", "default": true},
|
||||||
|
"gridAxis": {"type": "string", "enum": ["x", "y", "xy", "none"], "default": "x"},
|
||||||
|
"tickLine": {"type": "string", "enum": ["x", "y", "xy", "none"], "default": "y"},
|
||||||
|
"strokeDasharray": {"type": "string"},
|
||||||
|
"fillOpacity": {"type": "number", "default": 0.2},
|
||||||
|
"splitColors": {"type": "array"},
|
||||||
|
"areaChartProps": {"type": "object"},
|
||||||
|
"type": {"type": "string", "enum": ["default", "stacked", "percent", "split"], "default": "default"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BarChart": {
|
||||||
|
"description": "Bar chart for categorical data",
|
||||||
|
"props": {
|
||||||
|
"data": {"type": "array", "required": true},
|
||||||
|
"dataKey": {"type": "string", "required": true},
|
||||||
|
"series": {"type": "array", "required": true},
|
||||||
|
"h": {"type": "any"},
|
||||||
|
"w": {"type": "any"},
|
||||||
|
"orientation": {"type": "string", "enum": ["horizontal", "vertical"], "default": "vertical"},
|
||||||
|
"withLegend": {"type": "boolean", "default": false},
|
||||||
|
"withTooltip": {"type": "boolean", "default": true},
|
||||||
|
"withXAxis": {"type": "boolean", "default": true},
|
||||||
|
"withYAxis": {"type": "boolean", "default": true},
|
||||||
|
"gridAxis": {"type": "string", "enum": ["x", "y", "xy", "none"], "default": "x"},
|
||||||
|
"tickLine": {"type": "string", "enum": ["x", "y", "xy", "none"], "default": "y"},
|
||||||
|
"barProps": {"type": "object"},
|
||||||
|
"type": {"type": "string", "enum": ["default", "stacked", "percent", "waterfall"], "default": "default"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"LineChart": {
|
||||||
|
"description": "Line chart for trends",
|
||||||
|
"props": {
|
||||||
|
"data": {"type": "array", "required": true},
|
||||||
|
"dataKey": {"type": "string", "required": true},
|
||||||
|
"series": {"type": "array", "required": true},
|
||||||
|
"h": {"type": "any"},
|
||||||
|
"w": {"type": "any"},
|
||||||
|
"curveType": {"type": "string", "enum": ["bump", "linear", "natural", "monotone", "step", "stepBefore", "stepAfter"], "default": "monotone"},
|
||||||
|
"connectNulls": {"type": "boolean", "default": true},
|
||||||
|
"withDots": {"type": "boolean", "default": true},
|
||||||
|
"withLegend": {"type": "boolean", "default": false},
|
||||||
|
"withTooltip": {"type": "boolean", "default": true},
|
||||||
|
"withXAxis": {"type": "boolean", "default": true},
|
||||||
|
"withYAxis": {"type": "boolean", "default": true},
|
||||||
|
"gridAxis": {"type": "string", "enum": ["x", "y", "xy", "none"], "default": "x"},
|
||||||
|
"strokeWidth": {"type": "number", "default": 2}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PieChart": {
|
||||||
|
"description": "Pie chart for proportions",
|
||||||
|
"props": {
|
||||||
|
"data": {"type": "array", "required": true, "description": "Array of {name, value, color} objects"},
|
||||||
|
"h": {"type": "any"},
|
||||||
|
"w": {"type": "any"},
|
||||||
|
"withLabels": {"type": "boolean", "default": false},
|
||||||
|
"withLabelsLine": {"type": "boolean", "default": true},
|
||||||
|
"withTooltip": {"type": "boolean", "default": true},
|
||||||
|
"labelsPosition": {"type": "string", "enum": ["inside", "outside"], "default": "outside"},
|
||||||
|
"labelsType": {"type": "string", "enum": ["value", "percent"], "default": "value"},
|
||||||
|
"strokeWidth": {"type": "number", "default": 1},
|
||||||
|
"strokeColor": {"type": "string"},
|
||||||
|
"startAngle": {"type": "number", "default": 0},
|
||||||
|
"endAngle": {"type": "number", "default": 360}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DonutChart": {
|
||||||
|
"description": "Donut chart (pie with hole)",
|
||||||
|
"props": {
|
||||||
|
"data": {"type": "array", "required": true},
|
||||||
|
"h": {"type": "any"},
|
||||||
|
"w": {"type": "any"},
|
||||||
|
"withLabels": {"type": "boolean", "default": false},
|
||||||
|
"withLabelsLine": {"type": "boolean", "default": true},
|
||||||
|
"withTooltip": {"type": "boolean", "default": true},
|
||||||
|
"thickness": {"type": "number", "default": 20},
|
||||||
|
"chartLabel": {"type": "any"},
|
||||||
|
"strokeWidth": {"type": "number", "default": 1},
|
||||||
|
"strokeColor": {"type": "string"},
|
||||||
|
"startAngle": {"type": "number", "default": 0},
|
||||||
|
"endAngle": {"type": "number", "default": 360},
|
||||||
|
"paddingAngle": {"type": "number", "default": 0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DatePicker": {
|
||||||
|
"description": "Date picker calendar",
|
||||||
|
"props": {
|
||||||
|
"value": {"type": "string"},
|
||||||
|
"type": {"type": "string", "enum": ["default", "range", "multiple"], "default": "default"},
|
||||||
|
"defaultValue": {"type": "any"},
|
||||||
|
"allowDeselect": {"type": "boolean", "default": false},
|
||||||
|
"allowSingleDateInRange": {"type": "boolean", "default": false},
|
||||||
|
"numberOfColumns": {"type": "integer", "default": 1},
|
||||||
|
"columnsToScroll": {"type": "integer", "default": 1},
|
||||||
|
"ariaLabels": {"type": "object"},
|
||||||
|
"hideOutsideDates": {"type": "boolean", "default": false},
|
||||||
|
"hideWeekdays": {"type": "boolean", "default": false},
|
||||||
|
"weekendDays": {"type": "array", "default": [0, 6]},
|
||||||
|
"renderDay": {"type": "any"},
|
||||||
|
"minDate": {"type": "string"},
|
||||||
|
"maxDate": {"type": "string"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DatePickerInput": {
|
||||||
|
"description": "Date picker input field",
|
||||||
|
"props": {
|
||||||
|
"value": {"type": "string"},
|
||||||
|
"label": {"type": "any"},
|
||||||
|
"description": {"type": "any"},
|
||||||
|
"error": {"type": "any"},
|
||||||
|
"placeholder": {"type": "string"},
|
||||||
|
"clearable": {"type": "boolean", "default": false},
|
||||||
|
"type": {"type": "string", "enum": ["default", "range", "multiple"], "default": "default"},
|
||||||
|
"valueFormat": {"type": "string", "default": "MMMM D, YYYY"},
|
||||||
|
"size": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"radius": {"type": "string", "enum": ["xs", "sm", "md", "lg", "xl"], "default": "sm"},
|
||||||
|
"disabled": {"type": "boolean", "default": false},
|
||||||
|
"required": {"type": "boolean", "default": false},
|
||||||
|
"minDate": {"type": "string"},
|
||||||
|
"maxDate": {"type": "string"},
|
||||||
|
"popoverProps": {"type": "object"},
|
||||||
|
"dropdownType": {"type": "string", "enum": ["popover", "modal"], "default": "popover"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DatesProvider": {
|
||||||
|
"description": "Provider for date localization settings",
|
||||||
|
"props": {
|
||||||
|
"children": {"type": "any", "required": true},
|
||||||
|
"settings": {"type": "object", "description": "Locale and formatting settings"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ mcp>=0.9.0
|
|||||||
# Visualization
|
# Visualization
|
||||||
plotly>=5.18.0
|
plotly>=5.18.0
|
||||||
dash>=2.14.0
|
dash>=2.14.0
|
||||||
dash-mantine-components>=0.14.0
|
dash-mantine-components>=2.0.0
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
python-dotenv>=1.0.0
|
python-dotenv>=1.0.0
|
||||||
|
|||||||
262
mcp-servers/viz-platform/scripts/generate-dmc-registry.py
Normal file
262
mcp-servers/viz-platform/scripts/generate-dmc-registry.py
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generate DMC Component Registry from installed dash-mantine-components package.
|
||||||
|
|
||||||
|
This script introspects the installed DMC package and generates a JSON registry
|
||||||
|
file containing component definitions, props, types, and defaults.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python generate-dmc-registry.py [--output registry/dmc_X_Y.json]
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
- dash-mantine-components must be installed
|
||||||
|
- Run from the mcp-servers/viz-platform directory
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
import inspect
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from datetime import date
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict, List, Optional, get_type_hints
|
||||||
|
|
||||||
|
|
||||||
|
def get_dmc_version() -> Optional[str]:
|
||||||
|
"""Get installed DMC version."""
|
||||||
|
try:
|
||||||
|
from importlib.metadata import version
|
||||||
|
return version('dash-mantine-components')
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_component_categories() -> Dict[str, List[str]]:
|
||||||
|
"""Define component categories."""
|
||||||
|
return {
|
||||||
|
"buttons": ["Button", "ActionIcon", "CopyButton", "FileButton", "UnstyledButton"],
|
||||||
|
"inputs": [
|
||||||
|
"TextInput", "PasswordInput", "NumberInput", "Textarea",
|
||||||
|
"Select", "MultiSelect", "Checkbox", "Switch", "Radio",
|
||||||
|
"Slider", "RangeSlider", "ColorInput", "ColorPicker",
|
||||||
|
"DateInput", "DatePicker", "TimeInput"
|
||||||
|
],
|
||||||
|
"navigation": ["Anchor", "Breadcrumbs", "Burger", "NavLink", "Pagination", "Stepper", "Tabs"],
|
||||||
|
"feedback": ["Alert", "Loader", "Notification", "Progress", "RingProgress", "Skeleton"],
|
||||||
|
"overlays": ["Dialog", "Drawer", "HoverCard", "Menu", "Modal", "Popover", "Tooltip"],
|
||||||
|
"typography": ["Blockquote", "Code", "Highlight", "Mark", "Text", "Title"],
|
||||||
|
"layout": [
|
||||||
|
"AppShell", "AspectRatio", "Center", "Container", "Flex",
|
||||||
|
"Grid", "Group", "Paper", "SimpleGrid", "Space", "Stack"
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
"Accordion", "Avatar", "Badge", "Card", "Image",
|
||||||
|
"Indicator", "Kbd", "Spoiler", "Table", "ThemeIcon", "Timeline"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def extract_prop_type(prop_info: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
"""Extract prop type information from Dash component prop."""
|
||||||
|
result = {"type": "any"}
|
||||||
|
|
||||||
|
if 'type' not in prop_info:
|
||||||
|
return result
|
||||||
|
|
||||||
|
prop_type = prop_info['type']
|
||||||
|
|
||||||
|
if isinstance(prop_type, dict):
|
||||||
|
type_name = prop_type.get('name', 'any')
|
||||||
|
|
||||||
|
# Map Dash types to JSON schema types
|
||||||
|
type_mapping = {
|
||||||
|
'string': 'string',
|
||||||
|
'number': 'number',
|
||||||
|
'bool': 'boolean',
|
||||||
|
'boolean': 'boolean',
|
||||||
|
'array': 'array',
|
||||||
|
'object': 'object',
|
||||||
|
'node': 'any',
|
||||||
|
'element': 'any',
|
||||||
|
'any': 'any',
|
||||||
|
'func': 'any',
|
||||||
|
}
|
||||||
|
|
||||||
|
result['type'] = type_mapping.get(type_name, 'any')
|
||||||
|
|
||||||
|
# Handle enums
|
||||||
|
if type_name == 'enum' and 'value' in prop_type:
|
||||||
|
values = prop_type['value']
|
||||||
|
if isinstance(values, list):
|
||||||
|
enum_values = []
|
||||||
|
for v in values:
|
||||||
|
if isinstance(v, dict) and 'value' in v:
|
||||||
|
# Remove quotes from string values
|
||||||
|
val = v['value'].strip("'\"")
|
||||||
|
enum_values.append(val)
|
||||||
|
elif isinstance(v, str):
|
||||||
|
enum_values.append(v.strip("'\""))
|
||||||
|
if enum_values:
|
||||||
|
result['enum'] = enum_values
|
||||||
|
result['type'] = 'string'
|
||||||
|
|
||||||
|
# Handle union types
|
||||||
|
elif type_name == 'union' and 'value' in prop_type:
|
||||||
|
# For unions, just mark as any for simplicity
|
||||||
|
result['type'] = 'any'
|
||||||
|
|
||||||
|
elif isinstance(prop_type, str):
|
||||||
|
result['type'] = prop_type
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def extract_component_props(component_class) -> Dict[str, Any]:
|
||||||
|
"""Extract props from a Dash component class."""
|
||||||
|
props = {}
|
||||||
|
|
||||||
|
# Try to get _prop_names or similar
|
||||||
|
if hasattr(component_class, '_prop_names'):
|
||||||
|
prop_names = component_class._prop_names
|
||||||
|
else:
|
||||||
|
prop_names = []
|
||||||
|
|
||||||
|
# Try to get _type attribute for prop definitions
|
||||||
|
if hasattr(component_class, '_type'):
|
||||||
|
prop_types = getattr(component_class, '_type', {})
|
||||||
|
else:
|
||||||
|
prop_types = {}
|
||||||
|
|
||||||
|
# Get default values
|
||||||
|
if hasattr(component_class, '_default_props'):
|
||||||
|
defaults = component_class._default_props
|
||||||
|
else:
|
||||||
|
defaults = {}
|
||||||
|
|
||||||
|
# Try to extract from _prop_descriptions
|
||||||
|
if hasattr(component_class, '_prop_descriptions'):
|
||||||
|
descriptions = component_class._prop_descriptions
|
||||||
|
else:
|
||||||
|
descriptions = {}
|
||||||
|
|
||||||
|
for prop_name in prop_names:
|
||||||
|
if prop_name.startswith('_'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
prop_info = {}
|
||||||
|
|
||||||
|
# Get type info if available
|
||||||
|
if prop_name in prop_types:
|
||||||
|
prop_info = extract_prop_type({'type': prop_types[prop_name]})
|
||||||
|
else:
|
||||||
|
prop_info = {'type': 'any'}
|
||||||
|
|
||||||
|
# Add default if exists
|
||||||
|
if prop_name in defaults:
|
||||||
|
prop_info['default'] = defaults[prop_name]
|
||||||
|
|
||||||
|
# Add description if exists
|
||||||
|
if prop_name in descriptions:
|
||||||
|
prop_info['description'] = descriptions[prop_name]
|
||||||
|
|
||||||
|
props[prop_name] = prop_info
|
||||||
|
|
||||||
|
return props
|
||||||
|
|
||||||
|
|
||||||
|
def generate_registry() -> Dict[str, Any]:
|
||||||
|
"""Generate the component registry from installed DMC."""
|
||||||
|
try:
|
||||||
|
import dash_mantine_components as dmc
|
||||||
|
except ImportError:
|
||||||
|
print("ERROR: dash-mantine-components not installed")
|
||||||
|
print("Install with: pip install dash-mantine-components")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
version = get_dmc_version()
|
||||||
|
categories = get_component_categories()
|
||||||
|
|
||||||
|
registry = {
|
||||||
|
"version": version,
|
||||||
|
"generated": date.today().isoformat(),
|
||||||
|
"categories": categories,
|
||||||
|
"components": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get all components from categories
|
||||||
|
all_components = set()
|
||||||
|
for comp_list in categories.values():
|
||||||
|
all_components.update(comp_list)
|
||||||
|
|
||||||
|
# Extract props for each component
|
||||||
|
for comp_name in sorted(all_components):
|
||||||
|
if hasattr(dmc, comp_name):
|
||||||
|
comp_class = getattr(dmc, comp_name)
|
||||||
|
try:
|
||||||
|
props = extract_component_props(comp_class)
|
||||||
|
if props:
|
||||||
|
registry["components"][comp_name] = {
|
||||||
|
"description": comp_class.__doc__ or f"{comp_name} component",
|
||||||
|
"props": props
|
||||||
|
}
|
||||||
|
print(f" Extracted: {comp_name} ({len(props)} props)")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" Warning: Failed to extract {comp_name}: {e}")
|
||||||
|
else:
|
||||||
|
print(f" Warning: Component not found: {comp_name}")
|
||||||
|
|
||||||
|
return registry
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Generate DMC component registry from installed package"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--output', '-o',
|
||||||
|
type=str,
|
||||||
|
help='Output file path (default: auto-generated based on version)'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--dry-run',
|
||||||
|
action='store_true',
|
||||||
|
help='Print to stdout instead of writing file'
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
print("Generating DMC Component Registry...")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
registry = generate_registry()
|
||||||
|
|
||||||
|
print("=" * 50)
|
||||||
|
print(f"Generated registry for DMC {registry['version']}")
|
||||||
|
print(f"Total components: {len(registry['components'])}")
|
||||||
|
|
||||||
|
if args.dry_run:
|
||||||
|
print(json.dumps(registry, indent=2))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Determine output path
|
||||||
|
if args.output:
|
||||||
|
output_path = Path(args.output)
|
||||||
|
else:
|
||||||
|
version = registry['version']
|
||||||
|
if version:
|
||||||
|
major_minor = '_'.join(version.split('.')[:2])
|
||||||
|
output_path = Path(__file__).parent.parent / 'registry' / f'dmc_{major_minor}.json'
|
||||||
|
else:
|
||||||
|
output_path = Path(__file__).parent.parent / 'registry' / 'dmc_unknown.json'
|
||||||
|
|
||||||
|
# Create directory if needed
|
||||||
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# Write registry
|
||||||
|
with open(output_path, 'w') as f:
|
||||||
|
json.dump(registry, indent=2, fp=f)
|
||||||
|
|
||||||
|
print(f"Registry written to: {output_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user