development #184
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",
|
||||
"plotly>=5.18.0",
|
||||
"dash>=2.14.0",
|
||||
"dash-mantine-components>=0.14.0",
|
||||
"dash-mantine-components>=2.0.0",
|
||||
"python-dotenv>=1.0.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
|
||||
plotly>=5.18.0
|
||||
dash>=2.14.0
|
||||
dash-mantine-components>=0.14.0
|
||||
dash-mantine-components>=2.0.0
|
||||
|
||||
# Utilities
|
||||
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