mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
Move FakeMUI content to appropriate root-level folders by implementation:
**React Components → components/fakemui/**
- 537 components (inputs, surfaces, layout, data-display, feedback,
navigation, utils, atoms, lab, x, email, workflows)
- 416 SVG icons
- Full barrel exports in components/fakemui/index.ts
**QML Components → qml/**
- 104 Material Design 3 components (11 categories)
- 7 hybrid application views
- 8 desktop widgets
- qmldir module registration
**Python Bindings → python/fakemui/**
- 15 PyQt6 modules (120+ components)
- Full Python package structure with pyproject.toml
**SCSS/Styles → fakemui/** (renamed purpose)
- scss/ - Material Design 3 stylesheets
- styles/ - Component SCSS modules
- src/utils/ - Accessibility utilities
- index.ts now re-exports from components/fakemui/
This separation allows:
- React: import { Button } from '@metabuilder/components/fakemui'
- QML: import QmlComponents 1.0
- Python: from fakemui import Button, Card
- Backward compat: import { Button } from '@metabuilder/fakemui'
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
536 lines
19 KiB
Python
536 lines
19 KiB
Python
"""
|
|
FakeMUI Demo - Showcase all components.
|
|
|
|
Run with: python -m codex_task_runner.ui.fakemui.demo
|
|
"""
|
|
|
|
import sys
|
|
from datetime import date, datetime
|
|
from PyQt6.QtWidgets import QApplication, QMainWindow, QScrollArea, QWidget
|
|
from PyQt6.QtCore import Qt
|
|
from PyQt6.QtGui import QIcon
|
|
|
|
from . import (
|
|
# Inputs
|
|
Button, IconButton, TextField, Select, CheckBox, RadioButton,
|
|
Switch, Slider, ToggleButton, ToggleButtonGroup,
|
|
# Data Display
|
|
Avatar, Badge, Chip, Divider, Typography,
|
|
ListWidget, ListItem, ListItemText, ListItemIcon,
|
|
# Feedback
|
|
Alert, Spinner, LinearProgress, Skeleton,
|
|
# Surfaces
|
|
Paper, Card, CardHeader, CardContent, CardActions,
|
|
Accordion, AccordionSummary, AccordionDetails,
|
|
AppBar, Toolbar, Drawer,
|
|
# Navigation
|
|
Breadcrumbs, Link, TabWidget, Tab, Pagination,
|
|
# Layout
|
|
Box, Container, Stack, Grid,
|
|
# Utils
|
|
Dialog, DialogTitle, DialogContent, DialogActions,
|
|
ThemeProvider, apply_theme,
|
|
# Atoms
|
|
Title, Subtitle, Text, Section, EmptyState, LoadingState,
|
|
ErrorState, Panel, StatBadge,
|
|
# Lab Components
|
|
LoadingButton, Timeline, TimelineItem, TimelineSeparator,
|
|
TimelineConnector, TimelineContent, TimelineDot, TimelineOppositeContent,
|
|
TreeView, TreeItem, Masonry,
|
|
# MUI X Components
|
|
DataGrid, DataGridColumn, DatePicker, TimePicker, DateTimePicker,
|
|
# Theming
|
|
create_theme, use_theme, styled,
|
|
)
|
|
from .stylesheet import get_stylesheet
|
|
|
|
|
|
class DemoWindow(QMainWindow):
|
|
"""Main demo window showcasing all FakeMUI components."""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
self.setWindowTitle("FakeMUI Demo - PyQt6 Material Components")
|
|
self.setMinimumSize(1200, 800)
|
|
|
|
# Apply theme
|
|
apply_theme('light')
|
|
|
|
# Main container with scroll
|
|
scroll = QScrollArea()
|
|
scroll.setWidgetResizable(True)
|
|
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
|
|
# Content
|
|
content = Container(maxWidth='lg')
|
|
content.set_padding(24)
|
|
|
|
# Add sections
|
|
self._add_typography_section(content)
|
|
self._add_button_section(content)
|
|
self._add_input_section(content)
|
|
self._add_data_display_section(content)
|
|
self._add_feedback_section(content)
|
|
self._add_surface_section(content)
|
|
self._add_navigation_section(content)
|
|
self._add_layout_section(content)
|
|
self._add_lab_section(content)
|
|
self._add_x_section(content)
|
|
|
|
scroll.setWidget(content)
|
|
self.setCentralWidget(scroll)
|
|
|
|
def _add_typography_section(self, parent: Container):
|
|
"""Add typography demonstration."""
|
|
section = Section(title="Typography")
|
|
|
|
section.add_content(Title("Heading 1", level=1))
|
|
section.add_content(Title("Heading 2", level=2))
|
|
section.add_content(Title("Heading 3", level=3))
|
|
section.add_content(Subtitle("Subtitle 1", level=1))
|
|
section.add_content(Subtitle("Subtitle 2", level=2))
|
|
section.add_content(Text("Body text - Lorem ipsum dolor sit amet, consectetur adipiscing elit."))
|
|
section.add_content(Text("Caption text", variant='caption'))
|
|
|
|
parent.add_widget(section)
|
|
parent.add_widget(Divider())
|
|
|
|
def _add_button_section(self, parent: Container):
|
|
"""Add button demonstration."""
|
|
section = Section(title="Buttons")
|
|
|
|
# Regular buttons
|
|
row = Stack(direction='row', spacing=2)
|
|
row.add_widget(Button("Default"))
|
|
row.add_widget(Button("Primary", primary=True))
|
|
row.add_widget(Button("Secondary", secondary=True))
|
|
row.add_widget(Button("Outline", outline=True))
|
|
row.add_widget(Button("Ghost", ghost=True))
|
|
section.add_content(row)
|
|
|
|
# Sizes
|
|
row2 = Stack(direction='row', spacing=2)
|
|
row2.add_widget(Button("Small", primary=True, sm=True))
|
|
row2.add_widget(Button("Medium", primary=True))
|
|
row2.add_widget(Button("Large", primary=True, lg=True))
|
|
section.add_content(row2)
|
|
|
|
# States
|
|
row3 = Stack(direction='row', spacing=2)
|
|
row3.add_widget(Button("Disabled", disabled=True))
|
|
row3.add_widget(Button("Loading", loading=True, primary=True))
|
|
section.add_content(row3)
|
|
|
|
# Toggle buttons
|
|
toggle_group = ToggleButtonGroup(exclusive=True)
|
|
toggle_group.add_button(ToggleButton("Left", value="left", selected=True))
|
|
toggle_group.add_button(ToggleButton("Center", value="center"))
|
|
toggle_group.add_button(ToggleButton("Right", value="right"))
|
|
section.add_content(toggle_group)
|
|
|
|
parent.add_widget(section)
|
|
parent.add_widget(Divider())
|
|
|
|
def _add_input_section(self, parent: Container):
|
|
"""Add input demonstration."""
|
|
section = Section(title="Inputs")
|
|
|
|
# Text fields
|
|
section.add_content(TextField(label="Standard", placeholder="Enter text..."))
|
|
section.add_content(TextField(label="With helper", helperText="Some helpful text"))
|
|
section.add_content(TextField(label="Error state", error=True, helperText="This field has an error"))
|
|
section.add_content(TextField(label="Multiline", multiline=True, rows=3))
|
|
|
|
# Select
|
|
section.add_content(Select(
|
|
options=["Option 1", "Option 2", "Option 3"],
|
|
placeholder="Select an option"
|
|
))
|
|
|
|
# Checkboxes and Radios
|
|
row = Stack(direction='row', spacing=4)
|
|
row.add_widget(CheckBox("Checkbox 1", checked=True))
|
|
row.add_widget(CheckBox("Checkbox 2"))
|
|
row.add_widget(RadioButton("Radio 1", checked=True))
|
|
row.add_widget(RadioButton("Radio 2"))
|
|
section.add_content(row)
|
|
|
|
# Switch
|
|
row2 = Stack(direction='row', spacing=4)
|
|
row2.add_widget(Switch("Toggle switch"))
|
|
row2.add_widget(Switch("Enabled", checked=True))
|
|
section.add_content(row2)
|
|
|
|
# Slider
|
|
section.add_content(Slider(value=50))
|
|
|
|
parent.add_widget(section)
|
|
parent.add_widget(Divider())
|
|
|
|
def _add_data_display_section(self, parent: Container):
|
|
"""Add data display demonstration."""
|
|
section = Section(title="Data Display")
|
|
|
|
# Avatars
|
|
row = Stack(direction='row', spacing=2)
|
|
row.add_widget(Avatar(alt="John Doe", size=40))
|
|
row.add_widget(Avatar(alt="Jane Smith", size=48))
|
|
row.add_widget(Avatar(alt="Bob Wilson", size=56, variant='rounded'))
|
|
section.add_content(row)
|
|
|
|
# Chips
|
|
row2 = Stack(direction='row', spacing=1)
|
|
row2.add_widget(Chip("Default"))
|
|
row2.add_widget(Chip("Primary", color='primary'))
|
|
row2.add_widget(Chip("Outlined", variant='outlined'))
|
|
row2.add_widget(Chip("Deletable", deletable=True))
|
|
section.add_content(row2)
|
|
|
|
# List
|
|
list_widget = ListWidget()
|
|
|
|
item1 = ListItem(clickable=True)
|
|
item1.add_widget(ListItemText(primary="List Item 1", secondary="Secondary text"))
|
|
list_widget.add_item(item1)
|
|
|
|
item2 = ListItem(clickable=True, selected=True)
|
|
item2.add_widget(ListItemText(primary="Selected Item", secondary="This item is selected"))
|
|
list_widget.add_item(item2)
|
|
|
|
item3 = ListItem(clickable=True)
|
|
item3.add_widget(ListItemText(primary="List Item 3", secondary="Another item"))
|
|
list_widget.add_item(item3)
|
|
|
|
section.add_content(list_widget)
|
|
|
|
# Stats
|
|
row3 = Stack(direction='row', spacing=4)
|
|
row3.add_widget(StatBadge(label="Users", value="1,234"))
|
|
row3.add_widget(StatBadge(label="Revenue", value="$56K", color='success'))
|
|
row3.add_widget(StatBadge(label="Errors", value="12", color='error'))
|
|
section.add_content(row3)
|
|
|
|
parent.add_widget(section)
|
|
parent.add_widget(Divider())
|
|
|
|
def _add_feedback_section(self, parent: Container):
|
|
"""Add feedback demonstration."""
|
|
section = Section(title="Feedback")
|
|
|
|
# Alerts
|
|
section.add_content(Alert(title="Info", message="This is an info alert", severity='info'))
|
|
section.add_content(Alert(title="Success", message="This is a success alert", severity='success'))
|
|
section.add_content(Alert(title="Warning", message="This is a warning alert", severity='warning'))
|
|
section.add_content(Alert(title="Error", message="This is an error alert", severity='error'))
|
|
|
|
# Progress
|
|
section.add_content(Text("Linear Progress:"))
|
|
section.add_content(LinearProgress(value=60))
|
|
|
|
section.add_content(Text("Indeterminate Progress:"))
|
|
section.add_content(LinearProgress(variant='indeterminate'))
|
|
|
|
# Spinners
|
|
row = Stack(direction='row', spacing=4)
|
|
row.add_widget(Spinner(size=24))
|
|
row.add_widget(Spinner(size=40))
|
|
row.add_widget(Spinner(size=56, color='secondary'))
|
|
section.add_content(row)
|
|
|
|
# Skeletons
|
|
section.add_content(Text("Skeletons:"))
|
|
section.add_content(Skeleton(variant='text', width=200))
|
|
section.add_content(Skeleton(variant='rectangular', width=300, height=100))
|
|
|
|
parent.add_widget(section)
|
|
parent.add_widget(Divider())
|
|
|
|
def _add_surface_section(self, parent: Container):
|
|
"""Add surface demonstration."""
|
|
section = Section(title="Surfaces")
|
|
|
|
# Cards
|
|
row = Stack(direction='row', spacing=2)
|
|
|
|
card1 = Card()
|
|
card1.add_widget(CardHeader(title="Card Title", subheader="Card subtitle"))
|
|
card1.add_widget(CardContent())
|
|
content1 = card1.findChild(CardContent)
|
|
if content1:
|
|
content1.add_widget(Text("Card content goes here. This is a simple card example."))
|
|
card1.add_widget(CardActions())
|
|
actions1 = card1.findChild(CardActions)
|
|
if actions1:
|
|
actions1.add_widget(Button("Action 1", ghost=True))
|
|
actions1.add_widget(Button("Action 2", ghost=True))
|
|
row.add_widget(card1)
|
|
|
|
card2 = Card(raised=True)
|
|
card2.add_widget(CardHeader(title="Raised Card"))
|
|
card2.add_widget(CardContent())
|
|
content2 = card2.findChild(CardContent)
|
|
if content2:
|
|
content2.add_widget(Text("This card has elevation."))
|
|
row.add_widget(card2)
|
|
|
|
section.add_content(row)
|
|
|
|
# Accordion
|
|
accordion = Accordion()
|
|
summary = AccordionSummary()
|
|
summary.set_content("Accordion Header")
|
|
accordion.set_summary(summary)
|
|
details = AccordionDetails()
|
|
details.add_widget(Text("Accordion content that can be expanded or collapsed."))
|
|
accordion.set_details(details)
|
|
section.add_content(accordion)
|
|
|
|
# Paper
|
|
paper = Paper(elevation=2)
|
|
paper.add_widget(Text("This is a Paper component with elevation."))
|
|
paper.set_padding(16)
|
|
section.add_content(paper)
|
|
|
|
parent.add_widget(section)
|
|
parent.add_widget(Divider())
|
|
|
|
def _add_navigation_section(self, parent: Container):
|
|
"""Add navigation demonstration."""
|
|
section = Section(title="Navigation")
|
|
|
|
# Breadcrumbs
|
|
breadcrumbs = Breadcrumbs()
|
|
breadcrumbs.add_item(Link("Home"))
|
|
breadcrumbs.add_item(Link("Category"))
|
|
breadcrumbs.add_item(Link("Current Page"))
|
|
section.add_content(breadcrumbs)
|
|
|
|
# Tabs
|
|
row = Stack(direction='row', spacing=0)
|
|
row.add_widget(Tab(label="Tab 1", selected=True))
|
|
row.add_widget(Tab(label="Tab 2"))
|
|
row.add_widget(Tab(label="Tab 3"))
|
|
row.add_widget(Tab(label="Disabled", disabled=True))
|
|
section.add_content(row)
|
|
|
|
# Pagination
|
|
pagination = Pagination(count=10, page=1)
|
|
section.add_content(pagination)
|
|
|
|
# Links
|
|
row2 = Stack(direction='row', spacing=2)
|
|
row2.add_widget(Link("Primary Link"))
|
|
row2.add_widget(Link("Secondary Link", color='secondary'))
|
|
section.add_content(row2)
|
|
|
|
parent.add_widget(section)
|
|
parent.add_widget(Divider())
|
|
|
|
def _add_layout_section(self, parent: Container):
|
|
"""Add layout demonstration."""
|
|
section = Section(title="Layout")
|
|
|
|
# Stack
|
|
section.add_content(Text("Horizontal Stack:"))
|
|
h_stack = Stack(direction='row', spacing=2)
|
|
for i in range(4):
|
|
box = Paper(elevation=1)
|
|
box.add_widget(Text(f"Item {i+1}"))
|
|
box.set_padding(16)
|
|
h_stack.add_widget(box)
|
|
section.add_content(h_stack)
|
|
|
|
# Grid
|
|
section.add_content(Text("Grid Layout:"))
|
|
grid = Grid(container=True, spacing=2, columns=3)
|
|
for i in range(6):
|
|
box = Paper(elevation=1)
|
|
box.add_widget(Text(f"Grid Item {i+1}"))
|
|
box.set_padding(16)
|
|
grid.add_widget(box)
|
|
section.add_content(grid)
|
|
|
|
# States
|
|
section.add_content(Text("State Components:"))
|
|
row = Stack(direction='row', spacing=4)
|
|
|
|
empty = EmptyState(title="No data", description="Nothing to display here")
|
|
empty.setFixedWidth(250)
|
|
row.add_widget(empty)
|
|
|
|
loading = LoadingState(message="Loading data...")
|
|
loading.setFixedWidth(250)
|
|
row.add_widget(loading)
|
|
|
|
error = ErrorState(title="Error", message="Failed to load data")
|
|
error.setFixedWidth(250)
|
|
row.add_widget(error)
|
|
|
|
section.add_content(row)
|
|
|
|
parent.add_widget(section)
|
|
|
|
def _add_lab_section(self, parent: Container):
|
|
"""Add lab components demonstration."""
|
|
section = Section(title="Lab Components")
|
|
|
|
# LoadingButton
|
|
section.add_content(Text("Loading Buttons:"))
|
|
row = Stack(direction='row', spacing=2)
|
|
|
|
btn1 = LoadingButton("Submit", loading=False, color='primary')
|
|
row.add_widget(btn1)
|
|
|
|
btn2 = LoadingButton("Loading...", loading=True, color='primary')
|
|
row.add_widget(btn2)
|
|
|
|
btn3 = LoadingButton("Outlined", loading=True, variant='outlined', color='secondary')
|
|
row.add_widget(btn3)
|
|
|
|
section.add_content(row)
|
|
|
|
# Timeline
|
|
section.add_content(Text("Timeline:"))
|
|
timeline = Timeline()
|
|
|
|
# Item 1
|
|
item1 = TimelineItem()
|
|
opp1 = TimelineOppositeContent()
|
|
opp1.set_text("9:30 am")
|
|
item1.set_opposite_content(opp1)
|
|
|
|
sep1 = TimelineSeparator()
|
|
sep1.add_widget(TimelineDot(color='primary'))
|
|
sep1.add_widget(TimelineConnector())
|
|
item1.set_separator(sep1)
|
|
|
|
cont1 = TimelineContent()
|
|
cont1.set_text("Eat breakfast")
|
|
item1.set_content(cont1)
|
|
timeline.add_item(item1)
|
|
|
|
# Item 2
|
|
item2 = TimelineItem()
|
|
opp2 = TimelineOppositeContent()
|
|
opp2.set_text("10:00 am")
|
|
item2.set_opposite_content(opp2)
|
|
|
|
sep2 = TimelineSeparator()
|
|
sep2.add_widget(TimelineDot(color='success'))
|
|
sep2.add_widget(TimelineConnector())
|
|
item2.set_separator(sep2)
|
|
|
|
cont2 = TimelineContent()
|
|
cont2.set_text("Code review")
|
|
item2.set_content(cont2)
|
|
timeline.add_item(item2)
|
|
|
|
# Item 3
|
|
item3 = TimelineItem()
|
|
opp3 = TimelineOppositeContent()
|
|
opp3.set_text("12:00 pm")
|
|
item3.set_opposite_content(opp3)
|
|
|
|
sep3 = TimelineSeparator()
|
|
sep3.add_widget(TimelineDot(color='error', variant='outlined'))
|
|
item3.set_separator(sep3)
|
|
|
|
cont3 = TimelineContent()
|
|
cont3.set_text("Lunch meeting")
|
|
item3.set_content(cont3)
|
|
timeline.add_item(item3)
|
|
|
|
section.add_content(timeline)
|
|
|
|
# TreeView
|
|
section.add_content(Text("TreeView:"))
|
|
tree = TreeView()
|
|
tree.add_node("1", "📁 Documents")
|
|
tree.add_node("1.1", "📄 Report.pdf", parent_id="1")
|
|
tree.add_node("1.2", "📄 Notes.txt", parent_id="1")
|
|
tree.add_node("2", "📁 Images")
|
|
tree.add_node("2.1", "🖼️ Photo.jpg", parent_id="2")
|
|
tree.add_node("2.2", "🖼️ Logo.png", parent_id="2")
|
|
tree.add_node("3", "📁 Projects")
|
|
tree.add_node("3.1", "📁 Project A", parent_id="3")
|
|
tree.add_node("3.1.1", "📄 main.py", parent_id="3.1")
|
|
tree.setMaximumHeight(200)
|
|
section.add_content(tree)
|
|
|
|
parent.add_widget(section)
|
|
parent.add_widget(Divider())
|
|
|
|
def _add_x_section(self, parent: Container):
|
|
"""Add MUI X components demonstration."""
|
|
section = Section(title="MUI X Components")
|
|
|
|
# DataGrid
|
|
section.add_content(Text("DataGrid:"))
|
|
|
|
columns = [
|
|
DataGridColumn("id", "ID", width=60),
|
|
DataGridColumn("name", "Name", flex=1),
|
|
DataGridColumn("email", "Email", flex=1.5),
|
|
DataGridColumn("role", "Role"),
|
|
]
|
|
|
|
rows = [
|
|
{"id": 1, "name": "John Doe", "email": "john@example.com", "role": "Admin"},
|
|
{"id": 2, "name": "Jane Smith", "email": "jane@example.com", "role": "User"},
|
|
{"id": 3, "name": "Bob Wilson", "email": "bob@example.com", "role": "Editor"},
|
|
{"id": 4, "name": "Alice Brown", "email": "alice@example.com", "role": "User"},
|
|
{"id": 5, "name": "Charlie Davis", "email": "charlie@example.com", "role": "Viewer"},
|
|
]
|
|
|
|
grid = DataGrid(
|
|
rows=rows,
|
|
columns=columns,
|
|
page_size=5,
|
|
checkbox_selection=True,
|
|
density='standard'
|
|
)
|
|
grid.setMaximumHeight(300)
|
|
section.add_content(grid)
|
|
|
|
# DatePicker
|
|
section.add_content(Text("Date & Time Pickers:"))
|
|
row2 = Stack(direction='row', spacing=4)
|
|
|
|
date_picker = DatePicker(
|
|
label="Select Date",
|
|
value=date.today(),
|
|
clearable=True
|
|
)
|
|
row2.add_widget(date_picker)
|
|
|
|
time_picker = TimePicker(
|
|
label="Select Time"
|
|
)
|
|
row2.add_widget(time_picker)
|
|
|
|
datetime_picker = DateTimePicker(
|
|
label="Date & Time",
|
|
value=datetime.now()
|
|
)
|
|
row2.add_widget(datetime_picker)
|
|
|
|
section.add_content(row2)
|
|
|
|
parent.add_widget(section)
|
|
|
|
|
|
def main():
|
|
"""Run the demo application."""
|
|
app = QApplication(sys.argv)
|
|
app.setStyleSheet(get_stylesheet('light'))
|
|
|
|
window = DemoWindow()
|
|
window.show()
|
|
|
|
sys.exit(app.exec())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|