quantum-framework 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quantum/__init__.py +1 -0
- quantum/cli/__init__.py +2 -0
- quantum/cli/commands/__init__.py +15 -0
- quantum/cli/commands/build.py +417 -0
- quantum/cli/commands/dev.py +185 -0
- quantum/cli/commands/docs.py +329 -0
- quantum/cli/commands/lint.py +523 -0
- quantum/cli/commands/migrate.py +527 -0
- quantum/cli/commands/new.py +622 -0
- quantum/cli/commands/serve.py +190 -0
- quantum/cli/commands/test.py +193 -0
- quantum/cli/deploy.py +810 -0
- quantum/cli/hot_reload.py +951 -0
- quantum/cli/jobs.py +356 -0
- quantum/cli/mq.py +582 -0
- quantum/cli/pkg.py +390 -0
- quantum/cli/runner.py +547 -0
- quantum/cli/server_process.py +159 -0
- quantum/cli/utils.py +334 -0
- quantum/compiler/__init__.py +30 -0
- quantum/compiler/base_generator.py +367 -0
- quantum/compiler/cli.py +295 -0
- quantum/compiler/expression_transformer.py +444 -0
- quantum/compiler/javascript/__init__.py +10 -0
- quantum/compiler/javascript/generator.py +659 -0
- quantum/compiler/optimizer.py +270 -0
- quantum/compiler/python/__init__.py +10 -0
- quantum/compiler/python/generator.py +883 -0
- quantum/compiler/python/runtime.py +863 -0
- quantum/compiler/transpiler.py +330 -0
- quantum/core/__init__.py +3 -0
- quantum/core/ast_nodes.py +2611 -0
- quantum/core/expression_diagnostics.py +87 -0
- quantum/core/expression_stdlib.py +148 -0
- quantum/core/expressions.py +591 -0
- quantum/core/features/agents/src/__init__.py +30 -0
- quantum/core/features/agents/src/ast_node.py +540 -0
- quantum/core/features/conditionals/src/__init__.py +8 -0
- quantum/core/features/conditionals/src/ast_node.py +68 -0
- quantum/core/features/data_fetching/src/__init__.py +21 -0
- quantum/core/features/data_fetching/src/ast_node.py +312 -0
- quantum/core/features/data_fetching/src/desktop_adapter.py +351 -0
- quantum/core/features/data_fetching/src/html_adapter.py +474 -0
- quantum/core/features/data_fetching/src/parser.py +225 -0
- quantum/core/features/data_import/src/__init__.py +0 -0
- quantum/core/features/data_import/src/ast_node.py +291 -0
- quantum/core/features/data_import/src/runtime.py +538 -0
- quantum/core/features/dump/src/__init__.py +12 -0
- quantum/core/features/dump/src/ast_node.py +106 -0
- quantum/core/features/dump/src/parser.py +61 -0
- quantum/core/features/dump/src/runtime.py +246 -0
- quantum/core/features/functions/src/__init__.py +8 -0
- quantum/core/features/functions/src/ast_node.py +149 -0
- quantum/core/features/game_engine_2d/src/__init__.py +19 -0
- quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
- quantum/core/features/game_engine_2d/src/parser.py +983 -0
- quantum/core/features/invocation/src/__init__.py +0 -0
- quantum/core/features/invocation/src/ast_node.py +146 -0
- quantum/core/features/invocation/src/runtime.py +327 -0
- quantum/core/features/knowledge_base/src/__init__.py +6 -0
- quantum/core/features/knowledge_base/src/ast_node.py +113 -0
- quantum/core/features/knowledge_base/src/parser.py +82 -0
- quantum/core/features/logging/src/__init__.py +12 -0
- quantum/core/features/logging/src/ast_node.py +111 -0
- quantum/core/features/logging/src/parser.py +50 -0
- quantum/core/features/logging/src/runtime.py +190 -0
- quantum/core/features/loops/src/__init__.py +8 -0
- quantum/core/features/loops/src/ast_node.py +60 -0
- quantum/core/features/query/src/__init__.py +0 -0
- quantum/core/features/query/src/database_service.py +322 -0
- quantum/core/features/query/src/query_validators.py +20 -0
- quantum/core/features/state_management/src/__init__.py +11 -0
- quantum/core/features/state_management/src/ast_node.py +228 -0
- quantum/core/features/terminal_engine/src/__init__.py +21 -0
- quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
- quantum/core/features/terminal_engine/src/parser.py +361 -0
- quantum/core/features/testing_engine/src/__init__.py +41 -0
- quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
- quantum/core/features/testing_engine/src/parser.py +604 -0
- quantum/core/features/theming/src/__init__.py +48 -0
- quantum/core/features/theming/src/ast_node.py +137 -0
- quantum/core/features/theming/src/presets.py +405 -0
- quantum/core/features/ui_engine/src/__init__.py +20 -0
- quantum/core/features/ui_engine/src/ast_nodes.py +1854 -0
- quantum/core/features/ui_engine/src/parser.py +1106 -0
- quantum/core/features/websocket/src/__init__.py +24 -0
- quantum/core/features/websocket/src/ast_node.py +247 -0
- quantum/core/html_compat.py +299 -0
- quantum/core/parser.py +1235 -0
- quantum/core/parser_registry.py +213 -0
- quantum/core/parsers/__init__.py +76 -0
- quantum/core/parsers/ai/__init__.py +12 -0
- quantum/core/parsers/ai/agent_parser.py +106 -0
- quantum/core/parsers/ai/knowledge_parser.py +86 -0
- quantum/core/parsers/ai/llm_parser.py +78 -0
- quantum/core/parsers/ai/team_parser.py +88 -0
- quantum/core/parsers/base.py +322 -0
- quantum/core/parsers/composition/__init__.py +10 -0
- quantum/core/parsers/composition/import_parser.py +50 -0
- quantum/core/parsers/composition/slot_parser.py +48 -0
- quantum/core/parsers/control_flow/__init__.py +11 -0
- quantum/core/parsers/control_flow/if_parser.py +68 -0
- quantum/core/parsers/control_flow/loop_parser.py +105 -0
- quantum/core/parsers/control_flow/set_parser.py +89 -0
- quantum/core/parsers/data/__init__.py +12 -0
- quantum/core/parsers/data/data_parser.py +217 -0
- quantum/core/parsers/data/invoke_parser.py +116 -0
- quantum/core/parsers/data/query_parser.py +188 -0
- quantum/core/parsers/data/transaction_parser.py +77 -0
- quantum/core/parsers/events/__init__.py +9 -0
- quantum/core/parsers/events/dispatch_event_parser.py +44 -0
- quantum/core/parsers/forms/__init__.py +11 -0
- quantum/core/parsers/forms/action_parser.py +54 -0
- quantum/core/parsers/forms/flash_parser.py +34 -0
- quantum/core/parsers/forms/redirect_parser.py +33 -0
- quantum/core/parsers/functions/__init__.py +11 -0
- quantum/core/parsers/functions/function_parser.py +137 -0
- quantum/core/parsers/functions/param_parser.py +66 -0
- quantum/core/parsers/functions/return_parser.py +31 -0
- quantum/core/parsers/html/__init__.py +10 -0
- quantum/core/parsers/html/component_call_parser.py +130 -0
- quantum/core/parsers/html/html_parser.py +115 -0
- quantum/core/parsers/jobs/__init__.py +11 -0
- quantum/core/parsers/jobs/job_parser.py +71 -0
- quantum/core/parsers/jobs/schedule_parser.py +62 -0
- quantum/core/parsers/jobs/thread_parser.py +57 -0
- quantum/core/parsers/messaging/__init__.py +17 -0
- quantum/core/parsers/messaging/message_ack_parser.py +30 -0
- quantum/core/parsers/messaging/message_nack_parser.py +30 -0
- quantum/core/parsers/messaging/message_parser.py +114 -0
- quantum/core/parsers/messaging/queue_parser.py +61 -0
- quantum/core/parsers/messaging/websocket_parser.py +121 -0
- quantum/core/parsers/persistence/__init__.py +9 -0
- quantum/core/parsers/persistence/persist_parser.py +64 -0
- quantum/core/parsers/routing/__init__.py +9 -0
- quantum/core/parsers/routing/route_parser.py +41 -0
- quantum/core/parsers/scripting/__init__.py +12 -0
- quantum/core/parsers/scripting/pyclass_parser.py +62 -0
- quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
- quantum/core/parsers/scripting/pyimport_parser.py +52 -0
- quantum/core/parsers/scripting/python_parser.py +49 -0
- quantum/core/parsers/services/__init__.py +12 -0
- quantum/core/parsers/services/dump_parser.py +52 -0
- quantum/core/parsers/services/file_parser.py +48 -0
- quantum/core/parsers/services/log_parser.py +46 -0
- quantum/core/parsers/services/mail_parser.py +65 -0
- quantum/core/tiers.py +82 -0
- quantum/packages/__init__.py +28 -0
- quantum/packages/manager.py +413 -0
- quantum/packages/manifest.py +351 -0
- quantum/packages/registry.py +399 -0
- quantum/packages/resolver.py +336 -0
- quantum/plugins/__init__.py +33 -0
- quantum/plugins/hooks.py +329 -0
- quantum/plugins/loader.py +479 -0
- quantum/plugins/manifest.py +336 -0
- quantum/plugins/registry.py +371 -0
- quantum/runtime/__init__.py +28 -0
- quantum/runtime/action_handler.py +443 -0
- quantum/runtime/adapters/__init__.py +88 -0
- quantum/runtime/adapters/memory_adapter.py +690 -0
- quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
- quantum/runtime/adapters/redis_adapter.py +582 -0
- quantum/runtime/adapters/sqlite_adapter.py +414 -0
- quantum/runtime/agent_service.py +1133 -0
- quantum/runtime/api_server.py +86 -0
- quantum/runtime/ast_cache.py +506 -0
- quantum/runtime/auth_service.py +267 -0
- quantum/runtime/component.py +990 -0
- quantum/runtime/component_composer.py +319 -0
- quantum/runtime/component_resolver.py +174 -0
- quantum/runtime/database_service.py +598 -0
- quantum/runtime/email_service.py +162 -0
- quantum/runtime/error_handler.py +295 -0
- quantum/runtime/execution_context.py +286 -0
- quantum/runtime/executor_registry.py +171 -0
- quantum/runtime/executors/__init__.py +71 -0
- quantum/runtime/executors/ai/__init__.py +12 -0
- quantum/runtime/executors/ai/agent_executor.py +217 -0
- quantum/runtime/executors/ai/knowledge_executor.py +114 -0
- quantum/runtime/executors/ai/llm_executor.py +153 -0
- quantum/runtime/executors/ai/team_executor.py +171 -0
- quantum/runtime/executors/base.py +262 -0
- quantum/runtime/executors/control_flow/__init__.py +11 -0
- quantum/runtime/executors/control_flow/if_executor.py +93 -0
- quantum/runtime/executors/control_flow/loop_executor.py +307 -0
- quantum/runtime/executors/control_flow/set_executor.py +412 -0
- quantum/runtime/executors/data/__init__.py +12 -0
- quantum/runtime/executors/data/data_executor.py +145 -0
- quantum/runtime/executors/data/invoke_executor.py +176 -0
- quantum/runtime/executors/data/query_executor.py +256 -0
- quantum/runtime/executors/data/transaction_executor.py +91 -0
- quantum/runtime/executors/jobs/__init__.py +11 -0
- quantum/runtime/executors/jobs/job_executor.py +190 -0
- quantum/runtime/executors/jobs/schedule_executor.py +132 -0
- quantum/runtime/executors/jobs/thread_executor.py +127 -0
- quantum/runtime/executors/messaging/__init__.py +17 -0
- quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
- quantum/runtime/executors/messaging/message_executor.py +174 -0
- quantum/runtime/executors/messaging/queue_executor.py +103 -0
- quantum/runtime/executors/messaging/websocket_executor.py +197 -0
- quantum/runtime/executors/scripting/__init__.py +11 -0
- quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
- quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
- quantum/runtime/executors/scripting/python_executor.py +249 -0
- quantum/runtime/executors/services/__init__.py +12 -0
- quantum/runtime/executors/services/dump_executor.py +72 -0
- quantum/runtime/executors/services/file_executor.py +89 -0
- quantum/runtime/executors/services/log_executor.py +77 -0
- quantum/runtime/executors/services/mail_executor.py +81 -0
- quantum/runtime/expression_cache.py +498 -0
- quantum/runtime/file_upload_service.py +326 -0
- quantum/runtime/function_registry.py +118 -0
- quantum/runtime/game_builder.py +166 -0
- quantum/runtime/game_code_generator.py +2371 -0
- quantum/runtime/game_templates.py +2006 -0
- quantum/runtime/godot_code_generator.py +4681 -0
- quantum/runtime/godot_templates.py +1449 -0
- quantum/runtime/job_executor.py +1599 -0
- quantum/runtime/knowledge_service.py +500 -0
- quantum/runtime/llm_cache.py +100 -0
- quantum/runtime/llm_providers.py +704 -0
- quantum/runtime/llm_service.py +287 -0
- quantum/runtime/logging_setup.py +140 -0
- quantum/runtime/message_broker.py +364 -0
- quantum/runtime/message_queue_service.py +571 -0
- quantum/runtime/param_validation.py +184 -0
- quantum/runtime/pypy_compat.py +315 -0
- quantum/runtime/python_bridge.py +698 -0
- quantum/runtime/query_validators.py +304 -0
- quantum/runtime/renderer.py +733 -0
- quantum/runtime/service_container.py +444 -0
- quantum/runtime/terminal_builder.py +76 -0
- quantum/runtime/terminal_code_generator.py +607 -0
- quantum/runtime/terminal_templates.py +243 -0
- quantum/runtime/testing_builder.py +77 -0
- quantum/runtime/testing_code_generator.py +833 -0
- quantum/runtime/testing_templates.py +85 -0
- quantum/runtime/ui_builder.py +188 -0
- quantum/runtime/ui_desktop_adapter.py +1730 -0
- quantum/runtime/ui_desktop_templates.py +307 -0
- quantum/runtime/ui_html_adapter.py +2691 -0
- quantum/runtime/ui_html_templates.py +2297 -0
- quantum/runtime/ui_mobile_adapter.py +1832 -0
- quantum/runtime/ui_mobile_templates.py +1003 -0
- quantum/runtime/ui_textual_adapter.py +1866 -0
- quantum/runtime/ui_textual_templates.py +45 -0
- quantum/runtime/ui_tokens.py +465 -0
- quantum/runtime/ui_validator.py +365 -0
- quantum/runtime/validators.py +256 -0
- quantum/runtime/web_server.py +1766 -0
- quantum/runtime/websocket_adapter.py +501 -0
- quantum/runtime/websocket_service.py +585 -0
- quantum/runtime/websocket_transport.py +289 -0
- quantum/runtime/wsgi.py +101 -0
- quantum/utils/__init__.py +1 -0
- quantum_framework-0.9.0.dist-info/METADATA +244 -0
- quantum_framework-0.9.0.dist-info/RECORD +262 -0
- quantum_framework-0.9.0.dist-info/WHEEL +5 -0
- quantum_framework-0.9.0.dist-info/entry_points.txt +2 -0
- quantum_framework-0.9.0.dist-info/licenses/LICENSE +21 -0
- quantum_framework-0.9.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AST Nodes for Theming System
|
|
3
|
+
|
|
4
|
+
UIThemeNode: Represents <ui:theme> tag for theme configuration
|
|
5
|
+
UIColorNode: Represents <ui:color> tag for custom color definitions
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Dict, Any, List, Optional
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from quantum.core.ast_nodes import QuantumNode
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class UIColorNode(QuantumNode):
|
|
15
|
+
"""
|
|
16
|
+
Represents <ui:color> - Custom color definition within a theme.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
name: Color token name (e.g., 'primary', 'background', 'text')
|
|
20
|
+
value: CSS color value (e.g., '#ff6b6b', 'rgb(255, 107, 107)')
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
<ui:color name="primary" value="#3b82f6" />
|
|
24
|
+
<ui:color name="danger" value="rgb(239, 68, 68)" />
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self):
|
|
28
|
+
self.name: str = ""
|
|
29
|
+
self.value: str = ""
|
|
30
|
+
|
|
31
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
32
|
+
return {
|
|
33
|
+
"type": "ui_color",
|
|
34
|
+
"name": self.name,
|
|
35
|
+
"value": self.value,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
def validate(self) -> List[str]:
|
|
39
|
+
errors = []
|
|
40
|
+
if not self.name:
|
|
41
|
+
errors.append("Color name is required")
|
|
42
|
+
if not self.value:
|
|
43
|
+
errors.append(f"Color value is required for '{self.name}'")
|
|
44
|
+
return errors
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class UIThemeNode(QuantumNode):
|
|
48
|
+
"""
|
|
49
|
+
Represents <ui:theme> - Theme configuration for the UI.
|
|
50
|
+
|
|
51
|
+
Supports:
|
|
52
|
+
- Preset themes: 'light', 'dark'
|
|
53
|
+
- Custom themes with color definitions
|
|
54
|
+
- Runtime theme switching
|
|
55
|
+
|
|
56
|
+
Attributes:
|
|
57
|
+
name: Theme name (for custom themes)
|
|
58
|
+
preset: Preset theme to extend ('light', 'dark')
|
|
59
|
+
colors: List of custom color overrides
|
|
60
|
+
auto_switch: Enable automatic dark/light switching based on system preference
|
|
61
|
+
|
|
62
|
+
Examples:
|
|
63
|
+
<!-- Use dark preset -->
|
|
64
|
+
<ui:theme preset="dark" />
|
|
65
|
+
|
|
66
|
+
<!-- Custom theme extending light -->
|
|
67
|
+
<ui:theme name="ocean" preset="light">
|
|
68
|
+
<ui:color name="primary" value="#0ea5e9" />
|
|
69
|
+
<ui:color name="secondary" value="#06b6d4" />
|
|
70
|
+
</ui:theme>
|
|
71
|
+
|
|
72
|
+
<!-- Auto-switch based on system preference -->
|
|
73
|
+
<ui:theme preset="light" auto-switch="true" />
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
# Valid preset names
|
|
77
|
+
VALID_PRESETS = {'light', 'dark', 'high-contrast', 'sepia', 'nord', 'dracula'}
|
|
78
|
+
|
|
79
|
+
# Valid color token names (matching design tokens)
|
|
80
|
+
VALID_COLOR_NAMES = {
|
|
81
|
+
'primary', 'secondary', 'success', 'danger', 'warning', 'info',
|
|
82
|
+
'light', 'dark', 'background', 'text', 'border', 'muted',
|
|
83
|
+
# Extended color tokens
|
|
84
|
+
'surface', 'overlay', 'accent', 'focus',
|
|
85
|
+
# Font size tokens (for completeness)
|
|
86
|
+
'font-xs', 'font-sm', 'font-md', 'font-lg', 'font-xl', 'font-2xl',
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
def __init__(self):
|
|
90
|
+
self.name: Optional[str] = None
|
|
91
|
+
self.preset: str = "light" # Default to light theme
|
|
92
|
+
self.colors: List[UIColorNode] = []
|
|
93
|
+
self.auto_switch: bool = False
|
|
94
|
+
|
|
95
|
+
def add_color(self, color: UIColorNode):
|
|
96
|
+
"""Add a custom color override."""
|
|
97
|
+
self.colors.append(color)
|
|
98
|
+
|
|
99
|
+
def get_color(self, name: str) -> Optional[str]:
|
|
100
|
+
"""Get color value by name, or None if not defined."""
|
|
101
|
+
for color in self.colors:
|
|
102
|
+
if color.name == name:
|
|
103
|
+
return color.value
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
def get_color_overrides(self) -> Dict[str, str]:
|
|
107
|
+
"""Return all custom colors as a dict."""
|
|
108
|
+
return {c.name: c.value for c in self.colors}
|
|
109
|
+
|
|
110
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
111
|
+
return {
|
|
112
|
+
"type": "ui_theme",
|
|
113
|
+
"name": self.name,
|
|
114
|
+
"preset": self.preset,
|
|
115
|
+
"auto_switch": self.auto_switch,
|
|
116
|
+
"colors": [c.to_dict() for c in self.colors],
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
def validate(self) -> List[str]:
|
|
120
|
+
errors = []
|
|
121
|
+
|
|
122
|
+
# Validate preset
|
|
123
|
+
if self.preset and self.preset not in self.VALID_PRESETS:
|
|
124
|
+
errors.append(
|
|
125
|
+
f"Invalid theme preset '{self.preset}'. "
|
|
126
|
+
f"Valid presets: {', '.join(sorted(self.VALID_PRESETS))}"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Validate colors
|
|
130
|
+
for color in self.colors:
|
|
131
|
+
errors.extend(color.validate())
|
|
132
|
+
# Warn about unknown color names (soft validation)
|
|
133
|
+
if color.name and color.name not in self.VALID_COLOR_NAMES:
|
|
134
|
+
# This is a warning, not an error - custom colors are allowed
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
return errors
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Theme Presets for Quantum UI Engine
|
|
3
|
+
|
|
4
|
+
Provides predefined color schemes for light and dark modes.
|
|
5
|
+
Colors are defined as CSS custom properties (variables) that integrate
|
|
6
|
+
with the existing design tokens system.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Dict, Optional
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# ==========================================================================
|
|
13
|
+
# Light Theme (Default)
|
|
14
|
+
# ==========================================================================
|
|
15
|
+
|
|
16
|
+
THEME_LIGHT: Dict[str, str] = {
|
|
17
|
+
# Primary colors
|
|
18
|
+
'primary': '#3b82f6', # Blue 500
|
|
19
|
+
'secondary': '#64748b', # Slate 500
|
|
20
|
+
'success': '#22c55e', # Green 500
|
|
21
|
+
'danger': '#ef4444', # Red 500
|
|
22
|
+
'warning': '#f59e0b', # Amber 500
|
|
23
|
+
'info': '#06b6d4', # Cyan 500
|
|
24
|
+
|
|
25
|
+
# Neutral colors
|
|
26
|
+
'light': '#f8fafc', # Slate 50
|
|
27
|
+
'dark': '#1e293b', # Slate 800
|
|
28
|
+
'background': '#ffffff', # White
|
|
29
|
+
'text': '#1e293b', # Slate 800
|
|
30
|
+
'border': '#e2e8f0', # Slate 200
|
|
31
|
+
'muted': '#94a3b8', # Slate 400
|
|
32
|
+
|
|
33
|
+
# Extended colors
|
|
34
|
+
'surface': '#f8fafc', # Slate 50
|
|
35
|
+
'overlay': 'rgba(0,0,0,0.5)',
|
|
36
|
+
'accent': '#8b5cf6', # Violet 500
|
|
37
|
+
'focus': 'rgba(59,130,246,0.5)', # Primary with alpha
|
|
38
|
+
|
|
39
|
+
# UI elements
|
|
40
|
+
'radius': '6px',
|
|
41
|
+
'shadow': '0 1px 3px rgba(0,0,0,0.1)',
|
|
42
|
+
|
|
43
|
+
# Font sizes (rem units)
|
|
44
|
+
'font-xs': '0.75rem',
|
|
45
|
+
'font-sm': '0.875rem',
|
|
46
|
+
'font-md': '1rem',
|
|
47
|
+
'font-lg': '1.25rem',
|
|
48
|
+
'font-xl': '1.5rem',
|
|
49
|
+
'font-2xl': '2rem',
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# ==========================================================================
|
|
54
|
+
# Dark Theme
|
|
55
|
+
# ==========================================================================
|
|
56
|
+
|
|
57
|
+
THEME_DARK: Dict[str, str] = {
|
|
58
|
+
# Primary colors (slightly adjusted for dark bg)
|
|
59
|
+
'primary': '#60a5fa', # Blue 400
|
|
60
|
+
'secondary': '#94a3b8', # Slate 400
|
|
61
|
+
'success': '#4ade80', # Green 400
|
|
62
|
+
'danger': '#f87171', # Red 400
|
|
63
|
+
'warning': '#fbbf24', # Amber 400
|
|
64
|
+
'info': '#22d3ee', # Cyan 400
|
|
65
|
+
|
|
66
|
+
# Neutral colors (inverted for dark mode)
|
|
67
|
+
'light': '#334155', # Slate 700
|
|
68
|
+
'dark': '#f8fafc', # Slate 50
|
|
69
|
+
'background': '#0f172a', # Slate 900
|
|
70
|
+
'text': '#f1f5f9', # Slate 100
|
|
71
|
+
'border': '#334155', # Slate 700
|
|
72
|
+
'muted': '#64748b', # Slate 500
|
|
73
|
+
|
|
74
|
+
# Extended colors
|
|
75
|
+
'surface': '#1e293b', # Slate 800
|
|
76
|
+
'overlay': 'rgba(0,0,0,0.7)',
|
|
77
|
+
'accent': '#a78bfa', # Violet 400
|
|
78
|
+
'focus': 'rgba(96,165,250,0.5)', # Primary with alpha
|
|
79
|
+
|
|
80
|
+
# UI elements (same as light, could be customized)
|
|
81
|
+
'radius': '6px',
|
|
82
|
+
'shadow': '0 1px 3px rgba(0,0,0,0.3)',
|
|
83
|
+
|
|
84
|
+
# Font sizes (same as light)
|
|
85
|
+
'font-xs': '0.75rem',
|
|
86
|
+
'font-sm': '0.875rem',
|
|
87
|
+
'font-md': '1rem',
|
|
88
|
+
'font-lg': '1.25rem',
|
|
89
|
+
'font-xl': '1.5rem',
|
|
90
|
+
'font-2xl': '2rem',
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# ==========================================================================
|
|
95
|
+
# High Contrast Theme (Accessibility)
|
|
96
|
+
# ==========================================================================
|
|
97
|
+
|
|
98
|
+
THEME_HIGH_CONTRAST: Dict[str, str] = {
|
|
99
|
+
# Primary colors (high saturation)
|
|
100
|
+
'primary': '#0066ff', # Bright blue
|
|
101
|
+
'secondary': '#595959', # Dark gray
|
|
102
|
+
'success': '#00aa00', # Bright green
|
|
103
|
+
'danger': '#dd0000', # Bright red
|
|
104
|
+
'warning': '#cc6600', # Bright orange
|
|
105
|
+
'info': '#0088cc', # Bright cyan
|
|
106
|
+
|
|
107
|
+
# Neutral colors (maximum contrast)
|
|
108
|
+
'light': '#ffffff', # Pure white
|
|
109
|
+
'dark': '#000000', # Pure black
|
|
110
|
+
'background': '#ffffff', # White
|
|
111
|
+
'text': '#000000', # Black
|
|
112
|
+
'border': '#000000', # Black border
|
|
113
|
+
'muted': '#595959', # Dark gray
|
|
114
|
+
|
|
115
|
+
# Extended colors
|
|
116
|
+
'surface': '#f0f0f0', # Light gray
|
|
117
|
+
'overlay': 'rgba(0,0,0,0.7)',
|
|
118
|
+
'accent': '#6600cc', # Purple
|
|
119
|
+
'focus': 'rgba(0,102,255,0.5)',
|
|
120
|
+
|
|
121
|
+
# UI elements (thicker borders, no shadows)
|
|
122
|
+
'radius': '0px', # Sharp corners for clarity
|
|
123
|
+
'shadow': 'none',
|
|
124
|
+
|
|
125
|
+
# Font sizes (slightly larger)
|
|
126
|
+
'font-xs': '0.875rem',
|
|
127
|
+
'font-sm': '1rem',
|
|
128
|
+
'font-md': '1.125rem',
|
|
129
|
+
'font-lg': '1.375rem',
|
|
130
|
+
'font-xl': '1.625rem',
|
|
131
|
+
'font-2xl': '2.25rem',
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# ==========================================================================
|
|
136
|
+
# Sepia Theme (Reading/Paper)
|
|
137
|
+
# ==========================================================================
|
|
138
|
+
|
|
139
|
+
THEME_SEPIA: Dict[str, str] = {
|
|
140
|
+
# Primary colors (warm tones)
|
|
141
|
+
'primary': '#8b4513', # Saddle brown
|
|
142
|
+
'secondary': '#6b5344', # Warm gray
|
|
143
|
+
'success': '#5d8a4a', # Olive green
|
|
144
|
+
'danger': '#c24b3f', # Brick red
|
|
145
|
+
'warning': '#d4a03b', # Golden
|
|
146
|
+
'info': '#4a7a8a', # Teal
|
|
147
|
+
|
|
148
|
+
# Neutral colors (sepia tones)
|
|
149
|
+
'light': '#f4ecd8', # Cream
|
|
150
|
+
'dark': '#3c2f2f', # Dark brown
|
|
151
|
+
'background': '#faf4e8', # Warm white
|
|
152
|
+
'text': '#3c2f2f', # Dark brown
|
|
153
|
+
'border': '#d4c5a9', # Tan
|
|
154
|
+
'muted': '#8b7355', # Medium brown
|
|
155
|
+
|
|
156
|
+
# Extended colors
|
|
157
|
+
'surface': '#f0e6d2', # Light cream
|
|
158
|
+
'overlay': 'rgba(60,47,47,0.5)',
|
|
159
|
+
'accent': '#9a5b4a', # Terra cotta
|
|
160
|
+
'focus': 'rgba(139,69,19,0.3)',
|
|
161
|
+
|
|
162
|
+
# UI elements
|
|
163
|
+
'radius': '4px',
|
|
164
|
+
'shadow': '0 1px 3px rgba(60,47,47,0.1)',
|
|
165
|
+
|
|
166
|
+
# Font sizes
|
|
167
|
+
'font-xs': '0.75rem',
|
|
168
|
+
'font-sm': '0.875rem',
|
|
169
|
+
'font-md': '1rem',
|
|
170
|
+
'font-lg': '1.25rem',
|
|
171
|
+
'font-xl': '1.5rem',
|
|
172
|
+
'font-2xl': '2rem',
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# ==========================================================================
|
|
177
|
+
# Nord Theme (Popular dark theme)
|
|
178
|
+
# ==========================================================================
|
|
179
|
+
|
|
180
|
+
THEME_NORD: Dict[str, str] = {
|
|
181
|
+
# Nord color palette
|
|
182
|
+
'primary': '#88c0d0', # Nord8 - Frost
|
|
183
|
+
'secondary': '#81a1c1', # Nord9 - Frost
|
|
184
|
+
'success': '#a3be8c', # Nord14 - Aurora
|
|
185
|
+
'danger': '#bf616a', # Nord11 - Aurora
|
|
186
|
+
'warning': '#ebcb8b', # Nord13 - Aurora
|
|
187
|
+
'info': '#5e81ac', # Nord10 - Frost
|
|
188
|
+
|
|
189
|
+
# Neutral colors (Nord Polar Night)
|
|
190
|
+
'light': '#4c566a', # Nord3
|
|
191
|
+
'dark': '#eceff4', # Nord6 - Snow
|
|
192
|
+
'background': '#2e3440', # Nord0
|
|
193
|
+
'text': '#eceff4', # Nord6
|
|
194
|
+
'border': '#4c566a', # Nord3
|
|
195
|
+
'muted': '#d8dee9', # Nord4
|
|
196
|
+
|
|
197
|
+
# Extended colors
|
|
198
|
+
'surface': '#3b4252', # Nord1
|
|
199
|
+
'overlay': 'rgba(46,52,64,0.8)',
|
|
200
|
+
'accent': '#b48ead', # Nord15 - Aurora
|
|
201
|
+
'focus': 'rgba(136,192,208,0.4)',
|
|
202
|
+
|
|
203
|
+
# UI elements
|
|
204
|
+
'radius': '4px',
|
|
205
|
+
'shadow': '0 2px 8px rgba(0,0,0,0.3)',
|
|
206
|
+
|
|
207
|
+
# Font sizes
|
|
208
|
+
'font-xs': '0.75rem',
|
|
209
|
+
'font-sm': '0.875rem',
|
|
210
|
+
'font-md': '1rem',
|
|
211
|
+
'font-lg': '1.25rem',
|
|
212
|
+
'font-xl': '1.5rem',
|
|
213
|
+
'font-2xl': '2rem',
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# ==========================================================================
|
|
218
|
+
# Dracula Theme (Popular dark theme)
|
|
219
|
+
# ==========================================================================
|
|
220
|
+
|
|
221
|
+
THEME_DRACULA: Dict[str, str] = {
|
|
222
|
+
# Dracula color palette
|
|
223
|
+
'primary': '#bd93f9', # Purple
|
|
224
|
+
'secondary': '#6272a4', # Comment
|
|
225
|
+
'success': '#50fa7b', # Green
|
|
226
|
+
'danger': '#ff5555', # Red
|
|
227
|
+
'warning': '#ffb86c', # Orange
|
|
228
|
+
'info': '#8be9fd', # Cyan
|
|
229
|
+
|
|
230
|
+
# Neutral colors
|
|
231
|
+
'light': '#44475a', # Current Line
|
|
232
|
+
'dark': '#f8f8f2', # Foreground
|
|
233
|
+
'background': '#282a36', # Background
|
|
234
|
+
'text': '#f8f8f2', # Foreground
|
|
235
|
+
'border': '#44475a', # Current Line
|
|
236
|
+
'muted': '#6272a4', # Comment
|
|
237
|
+
|
|
238
|
+
# Extended colors
|
|
239
|
+
'surface': '#21222c', # Darker background
|
|
240
|
+
'overlay': 'rgba(40,42,54,0.9)',
|
|
241
|
+
'accent': '#ff79c6', # Pink
|
|
242
|
+
'focus': 'rgba(189,147,249,0.4)',
|
|
243
|
+
|
|
244
|
+
# UI elements
|
|
245
|
+
'radius': '6px',
|
|
246
|
+
'shadow': '0 2px 10px rgba(0,0,0,0.4)',
|
|
247
|
+
|
|
248
|
+
# Font sizes
|
|
249
|
+
'font-xs': '0.75rem',
|
|
250
|
+
'font-sm': '0.875rem',
|
|
251
|
+
'font-md': '1rem',
|
|
252
|
+
'font-lg': '1.25rem',
|
|
253
|
+
'font-xl': '1.5rem',
|
|
254
|
+
'font-2xl': '2rem',
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
# ==========================================================================
|
|
259
|
+
# Theme Presets Registry
|
|
260
|
+
# ==========================================================================
|
|
261
|
+
|
|
262
|
+
THEME_PRESETS: Dict[str, Dict[str, str]] = {
|
|
263
|
+
'light': THEME_LIGHT,
|
|
264
|
+
'dark': THEME_DARK,
|
|
265
|
+
'high-contrast': THEME_HIGH_CONTRAST,
|
|
266
|
+
'sepia': THEME_SEPIA,
|
|
267
|
+
'nord': THEME_NORD,
|
|
268
|
+
'dracula': THEME_DRACULA,
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def get_theme_preset(name: str) -> Optional[Dict[str, str]]:
|
|
273
|
+
"""Get a theme preset by name."""
|
|
274
|
+
return THEME_PRESETS.get(name)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def get_theme_css(
|
|
278
|
+
preset: str = 'light',
|
|
279
|
+
overrides: Optional[Dict[str, str]] = None,
|
|
280
|
+
auto_switch: bool = False
|
|
281
|
+
) -> str:
|
|
282
|
+
"""
|
|
283
|
+
Generate CSS for a theme.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
preset: Base theme preset ('light' or 'dark')
|
|
287
|
+
overrides: Custom color overrides to apply on top of preset
|
|
288
|
+
auto_switch: If True, adds media query for automatic dark/light switching
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
CSS string with custom properties
|
|
292
|
+
"""
|
|
293
|
+
base_theme = THEME_PRESETS.get(preset, THEME_LIGHT)
|
|
294
|
+
|
|
295
|
+
# Merge overrides
|
|
296
|
+
theme = dict(base_theme)
|
|
297
|
+
if overrides:
|
|
298
|
+
theme.update(overrides)
|
|
299
|
+
|
|
300
|
+
# Generate CSS variables
|
|
301
|
+
css_vars = _theme_to_css_vars(theme)
|
|
302
|
+
|
|
303
|
+
if auto_switch:
|
|
304
|
+
# Generate both light and dark with media query
|
|
305
|
+
light_vars = _theme_to_css_vars(THEME_LIGHT)
|
|
306
|
+
dark_vars = _theme_to_css_vars(THEME_DARK)
|
|
307
|
+
|
|
308
|
+
# Apply overrides to both if provided
|
|
309
|
+
if overrides:
|
|
310
|
+
light_theme = dict(THEME_LIGHT)
|
|
311
|
+
light_theme.update(overrides)
|
|
312
|
+
light_vars = _theme_to_css_vars(light_theme)
|
|
313
|
+
|
|
314
|
+
dark_theme = dict(THEME_DARK)
|
|
315
|
+
dark_theme.update(overrides)
|
|
316
|
+
dark_vars = _theme_to_css_vars(dark_theme)
|
|
317
|
+
|
|
318
|
+
return f""":root {{
|
|
319
|
+
{light_vars}
|
|
320
|
+
}}
|
|
321
|
+
|
|
322
|
+
@media (prefers-color-scheme: dark) {{
|
|
323
|
+
:root {{
|
|
324
|
+
{dark_vars}
|
|
325
|
+
}}
|
|
326
|
+
}}
|
|
327
|
+
|
|
328
|
+
[data-theme="light"] {{
|
|
329
|
+
{light_vars}
|
|
330
|
+
}}
|
|
331
|
+
|
|
332
|
+
[data-theme="dark"] {{
|
|
333
|
+
{dark_vars}
|
|
334
|
+
}}
|
|
335
|
+
"""
|
|
336
|
+
else:
|
|
337
|
+
# Single theme
|
|
338
|
+
return f""":root {{
|
|
339
|
+
{css_vars}
|
|
340
|
+
}}
|
|
341
|
+
|
|
342
|
+
[data-theme="{preset}"] {{
|
|
343
|
+
{css_vars}
|
|
344
|
+
}}
|
|
345
|
+
"""
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def _theme_to_css_vars(theme: Dict[str, str]) -> str:
|
|
349
|
+
"""Convert theme dict to CSS variable declarations."""
|
|
350
|
+
lines = []
|
|
351
|
+
for key, value in theme.items():
|
|
352
|
+
# Convert key to CSS variable name
|
|
353
|
+
css_var = f"--q-{key}"
|
|
354
|
+
lines.append(f" {css_var}: {value};")
|
|
355
|
+
return '\n'.join(lines)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
# ==========================================================================
|
|
359
|
+
# Runtime Theme Switching JavaScript
|
|
360
|
+
# ==========================================================================
|
|
361
|
+
|
|
362
|
+
THEME_SWITCH_JS = """\
|
|
363
|
+
<script>
|
|
364
|
+
(function() {
|
|
365
|
+
// Get initial theme from localStorage or default
|
|
366
|
+
var stored = localStorage.getItem('quantum-theme');
|
|
367
|
+
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
368
|
+
var initial = stored || (prefersDark ? 'dark' : 'light');
|
|
369
|
+
document.documentElement.setAttribute('data-theme', initial);
|
|
370
|
+
|
|
371
|
+
// Theme switching function
|
|
372
|
+
window.__quantumSetTheme = function(theme) {
|
|
373
|
+
document.documentElement.setAttribute('data-theme', theme);
|
|
374
|
+
localStorage.setItem('quantum-theme', theme);
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
// Toggle between light and dark
|
|
378
|
+
window.__quantumToggleTheme = function() {
|
|
379
|
+
var current = document.documentElement.getAttribute('data-theme') || 'light';
|
|
380
|
+
var next = current === 'light' ? 'dark' : 'light';
|
|
381
|
+
window.__quantumSetTheme(next);
|
|
382
|
+
return next;
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
// Get current theme
|
|
386
|
+
window.__quantumGetTheme = function() {
|
|
387
|
+
return document.documentElement.getAttribute('data-theme') || 'light';
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
// Listen for system preference changes (if auto-switch enabled)
|
|
391
|
+
if (window.matchMedia) {
|
|
392
|
+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
|
|
393
|
+
if (!localStorage.getItem('quantum-theme')) {
|
|
394
|
+
document.documentElement.setAttribute('data-theme', e.matches ? 'dark' : 'light');
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
})();
|
|
399
|
+
</script>
|
|
400
|
+
"""
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def get_theme_switch_js() -> str:
|
|
404
|
+
"""Get the JavaScript for runtime theme switching."""
|
|
405
|
+
return THEME_SWITCH_JS
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UI Engine - Multi-target UI components (ui: namespace)
|
|
3
|
+
|
|
4
|
+
Compiles declarative XML to HTML/CSS, Python Textual (TUI), or Desktop (pywebview).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .ast_nodes import (
|
|
8
|
+
UIWindowNode, UIHBoxNode, UIVBoxNode, UIPanelNode,
|
|
9
|
+
UITabPanelNode, UITabNode, UIGridNode, UIAccordionNode,
|
|
10
|
+
UISectionNode, UIDividedBoxNode, UIFormNode, UIFormItemNode,
|
|
11
|
+
UISpacerNode, UIScrollBoxNode,
|
|
12
|
+
UITextNode, UIButtonNode, UIInputNode, UICheckboxNode,
|
|
13
|
+
UIRadioNode, UISwitchNode, UISelectNode, UITableNode,
|
|
14
|
+
UIColumnNode, UIListNode, UIItemNode, UIImageNode,
|
|
15
|
+
UILinkNode, UIProgressNode, UITreeNode, UIMenuNode,
|
|
16
|
+
UIOptionNode, UILogNode, UIMarkdownNode, UIHeaderNode,
|
|
17
|
+
UIFooterNode, UIRuleNode, UILoadingNode, UIBadgeNode,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .parser import UIParser, UIParseError
|