superqode 0.1.5__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.
- superqode/__init__.py +33 -0
- superqode/acp/__init__.py +23 -0
- superqode/acp/client.py +913 -0
- superqode/acp/permission_screen.py +457 -0
- superqode/acp/types.py +480 -0
- superqode/acp_discovery.py +856 -0
- superqode/agent/__init__.py +22 -0
- superqode/agent/edit_strategies.py +334 -0
- superqode/agent/loop.py +892 -0
- superqode/agent/qe_report_templates.py +39 -0
- superqode/agent/system_prompts.py +353 -0
- superqode/agent_output.py +721 -0
- superqode/agent_stream.py +953 -0
- superqode/agents/__init__.py +59 -0
- superqode/agents/acp_registry.py +305 -0
- superqode/agents/client.py +249 -0
- superqode/agents/data/augmentcode.com.toml +51 -0
- superqode/agents/data/cagent.dev.toml +51 -0
- superqode/agents/data/claude.com.toml +60 -0
- superqode/agents/data/codeassistant.dev.toml +51 -0
- superqode/agents/data/codex.openai.com.toml +57 -0
- superqode/agents/data/fastagent.ai.toml +66 -0
- superqode/agents/data/geminicli.com.toml +77 -0
- superqode/agents/data/goose.block.xyz.toml +54 -0
- superqode/agents/data/junie.jetbrains.com.toml +56 -0
- superqode/agents/data/kimi.moonshot.cn.toml +57 -0
- superqode/agents/data/llmlingagent.dev.toml +51 -0
- superqode/agents/data/molt.bot.toml +49 -0
- superqode/agents/data/opencode.ai.toml +60 -0
- superqode/agents/data/stakpak.dev.toml +51 -0
- superqode/agents/data/vtcode.dev.toml +51 -0
- superqode/agents/discovery.py +266 -0
- superqode/agents/messaging.py +160 -0
- superqode/agents/persona.py +166 -0
- superqode/agents/registry.py +421 -0
- superqode/agents/schema.py +72 -0
- superqode/agents/unified.py +367 -0
- superqode/app/__init__.py +111 -0
- superqode/app/constants.py +314 -0
- superqode/app/css.py +366 -0
- superqode/app/models.py +118 -0
- superqode/app/suggester.py +125 -0
- superqode/app/widgets.py +1591 -0
- superqode/app_enhanced.py +399 -0
- superqode/app_main.py +17187 -0
- superqode/approval.py +312 -0
- superqode/atomic.py +296 -0
- superqode/commands/__init__.py +1 -0
- superqode/commands/acp.py +965 -0
- superqode/commands/agents.py +180 -0
- superqode/commands/auth.py +278 -0
- superqode/commands/config.py +374 -0
- superqode/commands/init.py +826 -0
- superqode/commands/providers.py +819 -0
- superqode/commands/qe.py +1145 -0
- superqode/commands/roles.py +380 -0
- superqode/commands/serve.py +172 -0
- superqode/commands/suggestions.py +127 -0
- superqode/commands/superqe.py +460 -0
- superqode/config/__init__.py +51 -0
- superqode/config/loader.py +812 -0
- superqode/config/schema.py +498 -0
- superqode/core/__init__.py +111 -0
- superqode/core/roles.py +281 -0
- superqode/danger.py +386 -0
- superqode/data/superqode-template.yaml +1522 -0
- superqode/design_system.py +1080 -0
- superqode/dialogs/__init__.py +6 -0
- superqode/dialogs/base.py +39 -0
- superqode/dialogs/model.py +130 -0
- superqode/dialogs/provider.py +870 -0
- superqode/diff_view.py +919 -0
- superqode/enterprise.py +21 -0
- superqode/evaluation/__init__.py +25 -0
- superqode/evaluation/adapters.py +93 -0
- superqode/evaluation/behaviors.py +89 -0
- superqode/evaluation/engine.py +209 -0
- superqode/evaluation/scenarios.py +96 -0
- superqode/execution/__init__.py +36 -0
- superqode/execution/linter.py +538 -0
- superqode/execution/modes.py +347 -0
- superqode/execution/resolver.py +283 -0
- superqode/execution/runner.py +642 -0
- superqode/file_explorer.py +811 -0
- superqode/file_viewer.py +471 -0
- superqode/flash.py +183 -0
- superqode/guidance/__init__.py +58 -0
- superqode/guidance/config.py +203 -0
- superqode/guidance/prompts.py +71 -0
- superqode/harness/__init__.py +54 -0
- superqode/harness/accelerator.py +291 -0
- superqode/harness/config.py +319 -0
- superqode/harness/validator.py +147 -0
- superqode/history.py +279 -0
- superqode/integrations/superopt_runner.py +124 -0
- superqode/logging/__init__.py +49 -0
- superqode/logging/adapters.py +219 -0
- superqode/logging/formatter.py +923 -0
- superqode/logging/integration.py +341 -0
- superqode/logging/sinks.py +170 -0
- superqode/logging/unified_log.py +417 -0
- superqode/lsp/__init__.py +26 -0
- superqode/lsp/client.py +544 -0
- superqode/main.py +1069 -0
- superqode/mcp/__init__.py +89 -0
- superqode/mcp/auth_storage.py +380 -0
- superqode/mcp/client.py +1236 -0
- superqode/mcp/config.py +319 -0
- superqode/mcp/integration.py +337 -0
- superqode/mcp/oauth.py +436 -0
- superqode/mcp/oauth_callback.py +385 -0
- superqode/mcp/types.py +290 -0
- superqode/memory/__init__.py +31 -0
- superqode/memory/feedback.py +342 -0
- superqode/memory/store.py +522 -0
- superqode/notifications.py +369 -0
- superqode/optimization/__init__.py +5 -0
- superqode/optimization/config.py +33 -0
- superqode/permissions/__init__.py +25 -0
- superqode/permissions/rules.py +488 -0
- superqode/plan.py +323 -0
- superqode/providers/__init__.py +33 -0
- superqode/providers/gateway/__init__.py +165 -0
- superqode/providers/gateway/base.py +228 -0
- superqode/providers/gateway/litellm_gateway.py +1170 -0
- superqode/providers/gateway/openresponses_gateway.py +436 -0
- superqode/providers/health.py +297 -0
- superqode/providers/huggingface/__init__.py +74 -0
- superqode/providers/huggingface/downloader.py +472 -0
- superqode/providers/huggingface/endpoints.py +442 -0
- superqode/providers/huggingface/hub.py +531 -0
- superqode/providers/huggingface/inference.py +394 -0
- superqode/providers/huggingface/transformers_runner.py +516 -0
- superqode/providers/local/__init__.py +100 -0
- superqode/providers/local/base.py +438 -0
- superqode/providers/local/discovery.py +418 -0
- superqode/providers/local/lmstudio.py +256 -0
- superqode/providers/local/mlx.py +457 -0
- superqode/providers/local/ollama.py +486 -0
- superqode/providers/local/sglang.py +268 -0
- superqode/providers/local/tgi.py +260 -0
- superqode/providers/local/tool_support.py +477 -0
- superqode/providers/local/vllm.py +258 -0
- superqode/providers/manager.py +1338 -0
- superqode/providers/models.py +1016 -0
- superqode/providers/models_dev.py +578 -0
- superqode/providers/openresponses/__init__.py +87 -0
- superqode/providers/openresponses/converters/__init__.py +17 -0
- superqode/providers/openresponses/converters/messages.py +343 -0
- superqode/providers/openresponses/converters/tools.py +268 -0
- superqode/providers/openresponses/schema/__init__.py +56 -0
- superqode/providers/openresponses/schema/models.py +585 -0
- superqode/providers/openresponses/streaming/__init__.py +5 -0
- superqode/providers/openresponses/streaming/parser.py +338 -0
- superqode/providers/openresponses/tools/__init__.py +21 -0
- superqode/providers/openresponses/tools/apply_patch.py +352 -0
- superqode/providers/openresponses/tools/code_interpreter.py +290 -0
- superqode/providers/openresponses/tools/file_search.py +333 -0
- superqode/providers/openresponses/tools/mcp_adapter.py +252 -0
- superqode/providers/registry.py +716 -0
- superqode/providers/usage.py +332 -0
- superqode/pure_mode.py +384 -0
- superqode/qr/__init__.py +23 -0
- superqode/qr/dashboard.py +781 -0
- superqode/qr/generator.py +1018 -0
- superqode/qr/templates.py +135 -0
- superqode/safety/__init__.py +41 -0
- superqode/safety/sandbox.py +413 -0
- superqode/safety/warnings.py +256 -0
- superqode/server/__init__.py +33 -0
- superqode/server/lsp_server.py +775 -0
- superqode/server/web.py +250 -0
- superqode/session/__init__.py +25 -0
- superqode/session/persistence.py +580 -0
- superqode/session/sharing.py +477 -0
- superqode/session.py +475 -0
- superqode/sidebar.py +2991 -0
- superqode/stream_view.py +648 -0
- superqode/styles/__init__.py +3 -0
- superqode/superqe/__init__.py +184 -0
- superqode/superqe/acp_runner.py +1064 -0
- superqode/superqe/constitution/__init__.py +62 -0
- superqode/superqe/constitution/evaluator.py +308 -0
- superqode/superqe/constitution/loader.py +432 -0
- superqode/superqe/constitution/schema.py +250 -0
- superqode/superqe/events.py +591 -0
- superqode/superqe/frameworks/__init__.py +65 -0
- superqode/superqe/frameworks/base.py +234 -0
- superqode/superqe/frameworks/e2e.py +263 -0
- superqode/superqe/frameworks/executor.py +237 -0
- superqode/superqe/frameworks/javascript.py +409 -0
- superqode/superqe/frameworks/python.py +373 -0
- superqode/superqe/frameworks/registry.py +92 -0
- superqode/superqe/mcp_tools/__init__.py +47 -0
- superqode/superqe/mcp_tools/core_tools.py +418 -0
- superqode/superqe/mcp_tools/registry.py +230 -0
- superqode/superqe/mcp_tools/testing_tools.py +167 -0
- superqode/superqe/noise.py +89 -0
- superqode/superqe/orchestrator.py +778 -0
- superqode/superqe/roles.py +609 -0
- superqode/superqe/session.py +713 -0
- superqode/superqe/skills/__init__.py +57 -0
- superqode/superqe/skills/base.py +106 -0
- superqode/superqe/skills/core_skills.py +899 -0
- superqode/superqe/skills/registry.py +90 -0
- superqode/superqe/verifier.py +101 -0
- superqode/superqe_cli.py +76 -0
- superqode/tool_call.py +358 -0
- superqode/tools/__init__.py +93 -0
- superqode/tools/agent_tools.py +496 -0
- superqode/tools/base.py +324 -0
- superqode/tools/batch_tool.py +133 -0
- superqode/tools/diagnostics.py +311 -0
- superqode/tools/edit_tools.py +653 -0
- superqode/tools/enhanced_base.py +515 -0
- superqode/tools/file_tools.py +269 -0
- superqode/tools/file_tracking.py +45 -0
- superqode/tools/lsp_tools.py +610 -0
- superqode/tools/network_tools.py +350 -0
- superqode/tools/permissions.py +400 -0
- superqode/tools/question_tool.py +324 -0
- superqode/tools/search_tools.py +598 -0
- superqode/tools/shell_tools.py +259 -0
- superqode/tools/todo_tools.py +121 -0
- superqode/tools/validation.py +80 -0
- superqode/tools/web_tools.py +639 -0
- superqode/tui.py +1152 -0
- superqode/tui_integration.py +875 -0
- superqode/tui_widgets/__init__.py +27 -0
- superqode/tui_widgets/widgets/__init__.py +18 -0
- superqode/tui_widgets/widgets/progress.py +185 -0
- superqode/tui_widgets/widgets/tool_display.py +188 -0
- superqode/undo_manager.py +574 -0
- superqode/utils/__init__.py +5 -0
- superqode/utils/error_handling.py +323 -0
- superqode/utils/fuzzy.py +257 -0
- superqode/widgets/__init__.py +477 -0
- superqode/widgets/agent_collab.py +390 -0
- superqode/widgets/agent_store.py +936 -0
- superqode/widgets/agent_switcher.py +395 -0
- superqode/widgets/animation_manager.py +284 -0
- superqode/widgets/code_context.py +356 -0
- superqode/widgets/command_palette.py +412 -0
- superqode/widgets/connection_status.py +537 -0
- superqode/widgets/conversation_history.py +470 -0
- superqode/widgets/diff_indicator.py +155 -0
- superqode/widgets/enhanced_status_bar.py +385 -0
- superqode/widgets/enhanced_toast.py +476 -0
- superqode/widgets/file_browser.py +809 -0
- superqode/widgets/file_reference.py +585 -0
- superqode/widgets/issue_timeline.py +340 -0
- superqode/widgets/leader_key.py +264 -0
- superqode/widgets/mode_switcher.py +445 -0
- superqode/widgets/model_picker.py +234 -0
- superqode/widgets/permission_preview.py +1205 -0
- superqode/widgets/prompt.py +358 -0
- superqode/widgets/provider_connect.py +725 -0
- superqode/widgets/pty_shell.py +587 -0
- superqode/widgets/qe_dashboard.py +321 -0
- superqode/widgets/resizable_sidebar.py +377 -0
- superqode/widgets/response_changes.py +218 -0
- superqode/widgets/response_display.py +528 -0
- superqode/widgets/rich_tool_display.py +613 -0
- superqode/widgets/sidebar_panels.py +1180 -0
- superqode/widgets/slash_complete.py +356 -0
- superqode/widgets/split_view.py +612 -0
- superqode/widgets/status_bar.py +273 -0
- superqode/widgets/superqode_display.py +786 -0
- superqode/widgets/thinking_display.py +815 -0
- superqode/widgets/throbber.py +87 -0
- superqode/widgets/toast.py +206 -0
- superqode/widgets/unified_output.py +1073 -0
- superqode/workspace/__init__.py +75 -0
- superqode/workspace/artifacts.py +472 -0
- superqode/workspace/coordinator.py +353 -0
- superqode/workspace/diff_tracker.py +429 -0
- superqode/workspace/git_guard.py +373 -0
- superqode/workspace/git_snapshot.py +526 -0
- superqode/workspace/manager.py +750 -0
- superqode/workspace/snapshot.py +357 -0
- superqode/workspace/watcher.py +535 -0
- superqode/workspace/worktree.py +440 -0
- superqode-0.1.5.dist-info/METADATA +204 -0
- superqode-0.1.5.dist-info/RECORD +288 -0
- superqode-0.1.5.dist-info/WHEEL +5 -0
- superqode-0.1.5.dist-info/entry_points.txt +3 -0
- superqode-0.1.5.dist-info/licenses/LICENSE +648 -0
- superqode-0.1.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Loading throbber/spinner widget."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from textual.app import ComposeResult
|
|
6
|
+
from textual.containers import Horizontal
|
|
7
|
+
from textual.reactive import reactive
|
|
8
|
+
from textual.widget import Widget
|
|
9
|
+
from textual.widgets import Static, LoadingIndicator
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Throbber(Widget):
|
|
13
|
+
"""
|
|
14
|
+
Loading overlay with spinner and message.
|
|
15
|
+
|
|
16
|
+
Used during async operations like agent connection.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
DEFAULT_CSS = """
|
|
20
|
+
Throbber {
|
|
21
|
+
layer: overlay;
|
|
22
|
+
align: center middle;
|
|
23
|
+
width: auto;
|
|
24
|
+
height: auto;
|
|
25
|
+
background: $surface 90%;
|
|
26
|
+
border: round $primary;
|
|
27
|
+
padding: 1 2;
|
|
28
|
+
display: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Throbber.visible {
|
|
32
|
+
display: block;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Throbber > Horizontal {
|
|
36
|
+
width: auto;
|
|
37
|
+
height: auto;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Throbber LoadingIndicator {
|
|
41
|
+
width: 4;
|
|
42
|
+
height: 1;
|
|
43
|
+
color: $primary;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Throbber #throbber-text {
|
|
47
|
+
margin-left: 1;
|
|
48
|
+
color: $text;
|
|
49
|
+
}
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
# State
|
|
53
|
+
visible: reactive[bool] = reactive(False)
|
|
54
|
+
message: reactive[str] = reactive("Loading...")
|
|
55
|
+
|
|
56
|
+
def __init__(self, message: str = "Loading...", **kwargs) -> None:
|
|
57
|
+
super().__init__(**kwargs)
|
|
58
|
+
self.message = message
|
|
59
|
+
|
|
60
|
+
def compose(self) -> ComposeResult:
|
|
61
|
+
with Horizontal():
|
|
62
|
+
yield LoadingIndicator()
|
|
63
|
+
yield Static(self.message, id="throbber-text")
|
|
64
|
+
|
|
65
|
+
def show(self, message: str | None = None) -> None:
|
|
66
|
+
"""Show the throbber with optional message."""
|
|
67
|
+
if message:
|
|
68
|
+
self.message = message
|
|
69
|
+
self.visible = True
|
|
70
|
+
self.add_class("visible")
|
|
71
|
+
|
|
72
|
+
def hide(self) -> None:
|
|
73
|
+
"""Hide the throbber."""
|
|
74
|
+
self.visible = False
|
|
75
|
+
self.remove_class("visible")
|
|
76
|
+
|
|
77
|
+
def watch_message(self, message: str) -> None:
|
|
78
|
+
"""React to message changes."""
|
|
79
|
+
try:
|
|
80
|
+
text_widget = self.query_one("#throbber-text", Static)
|
|
81
|
+
text_widget.update(message)
|
|
82
|
+
except Exception:
|
|
83
|
+
pass # Widget might not be mounted yet
|
|
84
|
+
|
|
85
|
+
def update_message(self, message: str) -> None:
|
|
86
|
+
"""Update the loading message."""
|
|
87
|
+
self.message = message
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""Toast notification widgets."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import ClassVar
|
|
7
|
+
|
|
8
|
+
from textual.app import ComposeResult
|
|
9
|
+
from textual.containers import Vertical
|
|
10
|
+
from textual.message import Message
|
|
11
|
+
from textual.reactive import reactive
|
|
12
|
+
from textual.timer import Timer
|
|
13
|
+
from textual.widget import Widget
|
|
14
|
+
from textual.widgets import Static
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ToastType(Enum):
|
|
18
|
+
"""Types of toast notifications."""
|
|
19
|
+
|
|
20
|
+
SUCCESS = "success"
|
|
21
|
+
ERROR = "error"
|
|
22
|
+
WARNING = "warning"
|
|
23
|
+
INFO = "info"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Toast(Widget):
|
|
27
|
+
"""
|
|
28
|
+
A single toast notification.
|
|
29
|
+
|
|
30
|
+
Auto-dismisses after a configurable duration.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
DEFAULT_CSS = """
|
|
34
|
+
Toast {
|
|
35
|
+
width: auto;
|
|
36
|
+
max-width: 60;
|
|
37
|
+
height: auto;
|
|
38
|
+
padding: 0 2;
|
|
39
|
+
margin: 0 0 1 0;
|
|
40
|
+
background: $surface;
|
|
41
|
+
border: round $primary;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Toast.success {
|
|
45
|
+
border: round $success;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Toast.success .toast-icon {
|
|
49
|
+
color: $success;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Toast.error {
|
|
53
|
+
border: round $error;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Toast.error .toast-icon {
|
|
57
|
+
color: $error;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
Toast.warning {
|
|
61
|
+
border: round $warning;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Toast.warning .toast-icon {
|
|
65
|
+
color: $warning;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
Toast.info {
|
|
69
|
+
border: round $primary;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Toast.info .toast-icon {
|
|
73
|
+
color: $primary;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
Toast .toast-content {
|
|
77
|
+
layout: horizontal;
|
|
78
|
+
height: auto;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
Toast .toast-icon {
|
|
82
|
+
width: 3;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Toast .toast-message {
|
|
86
|
+
color: $text;
|
|
87
|
+
}
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
ICONS: ClassVar[dict[ToastType, str]] = {
|
|
91
|
+
ToastType.SUCCESS: "✓",
|
|
92
|
+
ToastType.ERROR: "✗",
|
|
93
|
+
ToastType.WARNING: "⚠",
|
|
94
|
+
ToastType.INFO: "ℹ",
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
class Dismissed(Message):
|
|
98
|
+
"""Message sent when toast is dismissed."""
|
|
99
|
+
|
|
100
|
+
def __init__(self, toast: "Toast") -> None:
|
|
101
|
+
self.toast = toast
|
|
102
|
+
super().__init__()
|
|
103
|
+
|
|
104
|
+
def __init__(
|
|
105
|
+
self,
|
|
106
|
+
message: str,
|
|
107
|
+
toast_type: ToastType = ToastType.INFO,
|
|
108
|
+
duration: float = 3.0,
|
|
109
|
+
**kwargs,
|
|
110
|
+
) -> None:
|
|
111
|
+
super().__init__(**kwargs)
|
|
112
|
+
self.message = message
|
|
113
|
+
self.toast_type = toast_type
|
|
114
|
+
self.duration = duration
|
|
115
|
+
self._timer: Timer | None = None
|
|
116
|
+
|
|
117
|
+
def compose(self) -> ComposeResult:
|
|
118
|
+
icon = self.ICONS.get(self.toast_type, "ℹ")
|
|
119
|
+
with Vertical(classes="toast-content"):
|
|
120
|
+
yield Static(f"{icon} {self.message}", classes="toast-message")
|
|
121
|
+
|
|
122
|
+
def on_mount(self) -> None:
|
|
123
|
+
"""Start auto-dismiss timer on mount."""
|
|
124
|
+
self.add_class(self.toast_type.value)
|
|
125
|
+
if self.duration > 0:
|
|
126
|
+
self._timer = self.set_timer(self.duration, self._dismiss)
|
|
127
|
+
|
|
128
|
+
def _dismiss(self) -> None:
|
|
129
|
+
"""Dismiss the toast."""
|
|
130
|
+
self.post_message(self.Dismissed(self))
|
|
131
|
+
self.remove()
|
|
132
|
+
|
|
133
|
+
def dismiss(self) -> None:
|
|
134
|
+
"""Manually dismiss the toast."""
|
|
135
|
+
if self._timer:
|
|
136
|
+
self._timer.stop()
|
|
137
|
+
self._dismiss()
|
|
138
|
+
|
|
139
|
+
def on_click(self) -> None:
|
|
140
|
+
"""Dismiss on click."""
|
|
141
|
+
self.dismiss()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class ToastContainer(Widget):
|
|
145
|
+
"""
|
|
146
|
+
Container for toast notifications.
|
|
147
|
+
|
|
148
|
+
Manages multiple toasts with stacking.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
DEFAULT_CSS = """
|
|
152
|
+
ToastContainer {
|
|
153
|
+
layer: notification;
|
|
154
|
+
dock: top;
|
|
155
|
+
align: center top;
|
|
156
|
+
height: auto;
|
|
157
|
+
width: auto;
|
|
158
|
+
margin-top: 1;
|
|
159
|
+
}
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
def __init__(self, **kwargs) -> None:
|
|
163
|
+
super().__init__(**kwargs)
|
|
164
|
+
self._toasts: list[Toast] = []
|
|
165
|
+
|
|
166
|
+
def compose(self) -> ComposeResult:
|
|
167
|
+
yield from [] # Start empty
|
|
168
|
+
|
|
169
|
+
def show_toast(
|
|
170
|
+
self,
|
|
171
|
+
message: str,
|
|
172
|
+
toast_type: ToastType = ToastType.INFO,
|
|
173
|
+
duration: float = 3.0,
|
|
174
|
+
) -> Toast:
|
|
175
|
+
"""Show a new toast notification."""
|
|
176
|
+
toast = Toast(message, toast_type, duration)
|
|
177
|
+
self._toasts.append(toast)
|
|
178
|
+
self.mount(toast)
|
|
179
|
+
return toast
|
|
180
|
+
|
|
181
|
+
def success(self, message: str, duration: float = 3.0) -> Toast:
|
|
182
|
+
"""Show a success toast."""
|
|
183
|
+
return self.show_toast(message, ToastType.SUCCESS, duration)
|
|
184
|
+
|
|
185
|
+
def error(self, message: str, duration: float = 5.0) -> Toast:
|
|
186
|
+
"""Show an error toast."""
|
|
187
|
+
return self.show_toast(message, ToastType.ERROR, duration)
|
|
188
|
+
|
|
189
|
+
def warning(self, message: str, duration: float = 4.0) -> Toast:
|
|
190
|
+
"""Show a warning toast."""
|
|
191
|
+
return self.show_toast(message, ToastType.WARNING, duration)
|
|
192
|
+
|
|
193
|
+
def info(self, message: str, duration: float = 3.0) -> Toast:
|
|
194
|
+
"""Show an info toast."""
|
|
195
|
+
return self.show_toast(message, ToastType.INFO, duration)
|
|
196
|
+
|
|
197
|
+
def on_toast_dismissed(self, event: Toast.Dismissed) -> None:
|
|
198
|
+
"""Handle toast dismissal."""
|
|
199
|
+
if event.toast in self._toasts:
|
|
200
|
+
self._toasts.remove(event.toast)
|
|
201
|
+
|
|
202
|
+
def clear_all(self) -> None:
|
|
203
|
+
"""Clear all toasts."""
|
|
204
|
+
for toast in list(self._toasts):
|
|
205
|
+
toast.dismiss()
|
|
206
|
+
self._toasts.clear()
|