@assistkick/create 1.9.0 → 1.11.0
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.
- package/dist/src/scaffolder.d.ts +12 -1
- package/dist/src/scaffolder.js +40 -3
- package/dist/src/scaffolder.js.map +1 -1
- package/package.json +1 -1
- package/templates/assistkick-product-system/package.json +1 -1
- package/templates/assistkick-product-system/packages/backend/package.json +1 -0
- package/templates/assistkick-product-system/packages/backend/src/mcp/permission_mcp_server.ts +196 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/agents.ts +31 -7
- package/templates/assistkick-product-system/packages/backend/src/routes/auth.ts +15 -12
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.test.ts +95 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_files.ts +97 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_permission.ts +94 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_sessions.ts +189 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.test.ts +131 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/chat_upload.ts +94 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/files.test.ts +12 -3
- package/templates/assistkick-product-system/packages/backend/src/routes/files.ts +2 -2
- package/templates/assistkick-product-system/packages/backend/src/routes/git.ts +391 -23
- package/templates/assistkick-product-system/packages/backend/src/routes/git_branches.test.ts +306 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/git_connect.test.ts +133 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/pipeline.ts +66 -9
- package/templates/assistkick-product-system/packages/backend/src/routes/preview.ts +204 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/projects.test.ts +205 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/projects.ts +37 -9
- package/templates/assistkick-product-system/packages/backend/src/routes/skills.test.ts +139 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/skills.ts +95 -0
- package/templates/assistkick-product-system/packages/backend/src/routes/terminal.ts +5 -4
- package/templates/assistkick-product-system/packages/backend/src/routes/users.ts +4 -4
- package/templates/assistkick-product-system/packages/backend/src/routes/video.ts +8 -8
- package/templates/assistkick-product-system/packages/backend/src/routes/workflow_groups.ts +5 -5
- package/templates/assistkick-product-system/packages/backend/src/routes/workflows.ts +6 -6
- package/templates/assistkick-product-system/packages/backend/src/server.ts +107 -27
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.test.ts +105 -203
- package/templates/assistkick-product-system/packages/backend/src/services/agent_service.ts +76 -266
- package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.test.ts +427 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_cli_bridge.ts +345 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.test.ts +170 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_message_repository.ts +106 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.test.ts +217 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_session_service.ts +188 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.test.ts +1243 -0
- package/templates/assistkick-product-system/packages/backend/src/services/chat_ws_handler.ts +894 -0
- package/templates/assistkick-product-system/packages/backend/src/services/coherence-review.ts +3 -3
- package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.test.ts +85 -0
- package/templates/assistkick-product-system/packages/backend/src/services/dev_command_detector.ts +54 -0
- package/templates/assistkick-product-system/packages/backend/src/services/email_service.ts +13 -10
- package/templates/assistkick-product-system/packages/backend/src/services/init.ts +11 -3
- package/templates/assistkick-product-system/packages/backend/src/services/invitation_service.ts +1 -1
- package/templates/assistkick-product-system/packages/backend/src/services/password_reset_service.ts +1 -1
- package/templates/assistkick-product-system/packages/backend/src/services/permission_service.test.ts +243 -0
- package/templates/assistkick-product-system/packages/backend/src/services/permission_service.ts +259 -0
- package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.test.ts +172 -0
- package/templates/assistkick-product-system/packages/backend/src/services/preview_server_manager.ts +225 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.test.ts +29 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_service.ts +17 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.test.ts +255 -0
- package/templates/assistkick-product-system/packages/backend/src/services/project_workspace_service.ts +300 -25
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.test.ts +44 -0
- package/templates/assistkick-product-system/packages/backend/src/services/pty_session_manager.ts +62 -7
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.test.ts +77 -6
- package/templates/assistkick-product-system/packages/backend/src/services/ssh_key_service.ts +149 -14
- package/templates/assistkick-product-system/packages/backend/src/services/terminal_ws_handler.ts +2 -1
- package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.test.ts +45 -0
- package/templates/assistkick-product-system/packages/backend/src/services/title_generator_service.ts +157 -0
- package/templates/assistkick-product-system/packages/backend/src/services/tts_service.ts +4 -3
- package/templates/assistkick-product-system/packages/backend/src/services/video_render_service.ts +3 -3
- package/templates/assistkick-product-system/packages/frontend/package.json +5 -0
- package/templates/assistkick-product-system/packages/frontend/src/App.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/api/client.ts +336 -5
- package/templates/assistkick-product-system/packages/frontend/src/components/AgentsView.tsx +192 -12
- package/templates/assistkick-product-system/packages/frontend/src/components/AttachmentPreviewList.tsx +98 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/AutocompleteDropdown.tsx +65 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatAttachButton.tsx +56 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatDropZone.tsx +80 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageBubble.tsx +155 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageContent.tsx +182 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatMessageInput.tsx +233 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatSessionSidebar.tsx +218 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatStopButton.tsx +32 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatTodoSidebar.tsx +113 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ChatView.tsx +842 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/CommitMessageModal.tsx +82 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/DiagramOverlay.tsx +160 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx +5 -5
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTree.tsx +9 -10
- package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx +5 -5
- package/templates/assistkick-product-system/packages/frontend/src/components/FilesView.tsx +112 -41
- package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/components/HighlightedText.tsx +87 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ImageLightbox.tsx +192 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/KanbanView.tsx +2 -2
- package/templates/assistkick-product-system/packages/frontend/src/components/MentionPill.tsx +33 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/MermaidBlock.tsx +148 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/PermissionDialog.tsx +91 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/PermissionModeSelector.tsx +229 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ProjectSelector.tsx +249 -83
- package/templates/assistkick-product-system/packages/frontend/src/components/QueuedMessageBubble.tsx +38 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/SidePanel.tsx +212 -117
- package/templates/assistkick-product-system/packages/frontend/src/components/SystemPromptAccordion.tsx +48 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/TaskIcon.tsx +11 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/TerminalView.tsx +25 -9
- package/templates/assistkick-product-system/packages/frontend/src/components/ToolDiffView.tsx +114 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ToolResultCard.tsx +87 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/ToolUseCard.tsx +149 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/Toolbar.tsx +25 -8
- package/templates/assistkick-product-system/packages/frontend/src/components/UnifiedGitWidget.tsx +722 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/GroupNode.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/NodePalette.tsx +2 -1
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/ProgrammableNode.tsx +178 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowCanvas.tsx +3 -0
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/WorkflowMonitorModal.tsx +103 -9
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/monitor_nodes.tsx +26 -2
- package/templates/assistkick-product-system/packages/frontend/src/components/workflow/workflow_types.ts +42 -1
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useDocumentTitle.ts +11 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/useProjects.ts +1 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/use_chat_stream.ts +826 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/use_file_tree_cache.ts +69 -0
- package/templates/assistkick-product-system/packages/frontend/src/hooks/use_mention_autocomplete.ts +284 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.test.ts +183 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/attachment_manager.ts +150 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.test.ts +305 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/chat_message_helpers.ts +113 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.test.ts +157 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/context_usage_helpers.ts +95 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.test.ts +65 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/mermaid_helpers.ts +110 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/message_queue.ts +66 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.test.ts +124 -0
- package/templates/assistkick-product-system/packages/frontend/src/lib/tool_use_summary.ts +112 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/AgentsRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/ChatRoute.tsx +8 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/CoherenceRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/DashboardLayout.tsx +0 -4
- package/templates/assistkick-product-system/packages/frontend/src/routes/DesignSystemRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/FilesRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/GraphRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/KanbanRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/TerminalRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/UsersRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/VideographyRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/WorkflowsRoute.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/accept_invitation.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/forgot_password.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/login.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/register.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/routes/reset_password.tsx +2 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useAttachmentStore.ts +66 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useChatSessionStore.ts +107 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useMessageQueueStore.ts +110 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/usePreviewStore.ts +78 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useProjectStore.ts +7 -0
- package/templates/assistkick-product-system/packages/frontend/src/stores/useSidePanelStore.ts +6 -1
- package/templates/assistkick-product-system/packages/frontend/src/styles/index.css +30 -357
- package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.test.ts +115 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/parse_node_markdown.ts +91 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.test.ts +30 -0
- package/templates/assistkick-product-system/packages/frontend/src/utils/preview_utils.ts +3 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0015_magenta_jazinda.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0016_giant_xorn.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0017_sloppy_mentor.sql +6 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0018_vengeful_kabuki.sql +9 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0019_careful_sentinels.sql +8 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0020_clever_spot.sql +27 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0021_graceful_hex.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0022_short_kingpin.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0023_ambiguous_sharon_carter.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/0024_fat_unus.sql +1 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0015_snapshot.json +1552 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0016_snapshot.json +1560 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0017_snapshot.json +1598 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0018_snapshot.json +1657 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0019_snapshot.json +1709 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0020_snapshot.json +1733 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0021_snapshot.json +1740 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0022_snapshot.json +1755 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0023_snapshot.json +1762 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/0024_snapshot.json +1769 -0
- package/templates/assistkick-product-system/packages/shared/db/migrations/meta/_journal.json +70 -0
- package/templates/assistkick-product-system/packages/shared/db/schema.ts +40 -1
- package/templates/assistkick-product-system/packages/shared/lib/claude-service.test.ts +236 -0
- package/templates/assistkick-product-system/packages/shared/lib/claude-service.ts +46 -5
- package/templates/assistkick-product-system/packages/shared/lib/git_workflow.ts +65 -39
- package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.test.ts +173 -0
- package/templates/assistkick-product-system/packages/shared/lib/programmable_node_executor.ts +213 -0
- package/templates/assistkick-product-system/packages/shared/lib/validator.test.ts +70 -0
- package/templates/assistkick-product-system/packages/shared/lib/validator.ts +17 -1
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.test.ts +803 -27
- package/templates/assistkick-product-system/packages/shared/lib/workflow_engine.ts +502 -68
- package/templates/assistkick-product-system/packages/shared/lib/workflow_orchestrator.ts +4 -4
- package/templates/assistkick-product-system/packages/shared/package.json +2 -1
- package/templates/assistkick-product-system/packages/shared/test_fixtures/hanging_stream.mjs +46 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.test.ts +44 -0
- package/templates/assistkick-product-system/packages/shared/tools/add_node.ts +7 -0
- package/templates/assistkick-product-system/packages/shared/tools/remove_node.ts +2 -1
- package/templates/assistkick-product-system/packages/shared/tools/resolve_question.ts +2 -1
- package/templates/assistkick-product-system/packages/shared/tools/update_node.ts +2 -1
- package/templates/assistkick-product-system/tests/message_queue.test.ts +178 -0
- package/templates/assistkick-product-system/tests/message_queue_per_session.test.ts +143 -0
- package/templates/skills/assistkick-bootstrap/SKILL.md +26 -26
- package/templates/skills/assistkick-code-reviewer/SKILL.md +45 -46
- package/templates/skills/assistkick-db-explorer/SKILL.md +13 -13
- package/templates/skills/assistkick-debugger/SKILL.md +23 -23
- package/templates/skills/assistkick-developer/SKILL.md +59 -63
- package/templates/skills/assistkick-interview/SKILL.md +26 -26
- package/templates/skills/assistkick-video-composition-agent/SKILL.md +231 -0
- package/templates/skills/assistkick-video-script-writer/SKILL.md +136 -0
package/templates/assistkick-product-system/packages/frontend/src/components/CommitMessageModal.tsx
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Commit Message Modal — prompts user to enter a commit message before switching branches
|
|
3
|
+
* when there are uncommitted changes.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { useState, useCallback, useRef, useEffect } from 'react';
|
|
7
|
+
|
|
8
|
+
interface CommitMessageModalProps {
|
|
9
|
+
isOpen: boolean;
|
|
10
|
+
targetBranch: string;
|
|
11
|
+
onConfirm: (message: string) => void;
|
|
12
|
+
onCancel: () => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const CommitMessageModal = ({ isOpen, targetBranch, onConfirm, onCancel }: CommitMessageModalProps) => {
|
|
16
|
+
const [message, setMessage] = useState('');
|
|
17
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (isOpen) {
|
|
21
|
+
setMessage('');
|
|
22
|
+
setTimeout(() => inputRef.current?.focus(), 50);
|
|
23
|
+
}
|
|
24
|
+
}, [isOpen]);
|
|
25
|
+
|
|
26
|
+
const handleSubmit = useCallback((e: React.FormEvent) => {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
const trimmed = message.trim();
|
|
29
|
+
if (!trimmed) return;
|
|
30
|
+
onConfirm(trimmed);
|
|
31
|
+
}, [message, onConfirm]);
|
|
32
|
+
|
|
33
|
+
if (!isOpen) return null;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-[1000]" onClick={onCancel}>
|
|
37
|
+
<div className="bg-surface border border-edge rounded-xl p-6 w-[440px] max-w-[90vw] shadow-[0_8px_32px_rgba(0,0,0,0.3)]" onClick={e => e.stopPropagation()}>
|
|
38
|
+
<div className="flex justify-between items-center mb-4">
|
|
39
|
+
<h2 className="m-0 text-lg text-content">Uncommitted Changes</h2>
|
|
40
|
+
<button className="bg-none border-none text-[22px] text-content-secondary cursor-pointer px-1 leading-none hover:text-content" onClick={onCancel} type="button">×</button>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<p className="text-[13px] text-content-secondary mb-3">
|
|
44
|
+
You have uncommitted changes. Enter a commit message to save them before switching to <span className="font-mono text-accent">{targetBranch}</span>.
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
<form onSubmit={handleSubmit} noValidate>
|
|
48
|
+
<div className="flex flex-col gap-1">
|
|
49
|
+
<label className="font-mono text-[11px] font-semibold text-content-secondary uppercase tracking-wider" htmlFor="commit-message">
|
|
50
|
+
Commit message
|
|
51
|
+
</label>
|
|
52
|
+
<input
|
|
53
|
+
ref={inputRef}
|
|
54
|
+
id="commit-message"
|
|
55
|
+
className="w-full h-9 px-2.5 bg-surface-raised border border-edge rounded text-content font-mono text-[13px] outline-none transition-[border-color] duration-150 focus:border-accent placeholder:text-content-muted"
|
|
56
|
+
value={message}
|
|
57
|
+
onChange={e => setMessage(e.target.value)}
|
|
58
|
+
placeholder="Save work before switching branch..."
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div className="flex gap-2 mt-4">
|
|
63
|
+
<button
|
|
64
|
+
className="flex-1 h-9 bg-transparent border border-edge rounded text-content-secondary font-mono text-[13px] cursor-pointer transition-[background,color] duration-150 hover:bg-surface-raised"
|
|
65
|
+
type="button"
|
|
66
|
+
onClick={onCancel}
|
|
67
|
+
>
|
|
68
|
+
Cancel
|
|
69
|
+
</button>
|
|
70
|
+
<button
|
|
71
|
+
className="flex-1 h-9 bg-transparent border border-accent rounded text-accent font-mono text-[13px] cursor-pointer transition-[background,color] duration-150 hover:bg-accent hover:text-white disabled:opacity-40 disabled:cursor-default disabled:hover:bg-transparent disabled:hover:text-accent"
|
|
72
|
+
type="submit"
|
|
73
|
+
disabled={!message.trim()}
|
|
74
|
+
>
|
|
75
|
+
Commit & Switch
|
|
76
|
+
</button>
|
|
77
|
+
</div>
|
|
78
|
+
</form>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
};
|
package/templates/assistkick-product-system/packages/frontend/src/components/DiagramOverlay.tsx
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DiagramOverlay — fullscreen overlay for viewing a mermaid SVG diagram.
|
|
3
|
+
*
|
|
4
|
+
* Supports zoom (scroll wheel / pinch) and pan (click-drag).
|
|
5
|
+
* Closed via the X button or pressing Escape.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
9
|
+
import { X, ZoomIn, ZoomOut, RotateCcw } from 'lucide-react';
|
|
10
|
+
import { clampZoom } from '../lib/mermaid_helpers';
|
|
11
|
+
|
|
12
|
+
const ZOOM_STEP = 0.15;
|
|
13
|
+
|
|
14
|
+
interface DiagramOverlayProps {
|
|
15
|
+
svgHtml: string;
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const DiagramOverlay = ({ svgHtml, onClose }: DiagramOverlayProps) => {
|
|
20
|
+
const [zoom, setZoom] = useState(1);
|
|
21
|
+
const [pan, setPan] = useState({ x: 0, y: 0 });
|
|
22
|
+
const [dragging, setDragging] = useState(false);
|
|
23
|
+
const dragStart = useRef({ x: 0, y: 0 });
|
|
24
|
+
const panStart = useRef({ x: 0, y: 0 });
|
|
25
|
+
const contentRef = useRef<HTMLDivElement>(null);
|
|
26
|
+
|
|
27
|
+
// Escape key handler
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
30
|
+
if (e.key === 'Escape') {
|
|
31
|
+
onClose();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
36
|
+
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
37
|
+
}, [onClose]);
|
|
38
|
+
|
|
39
|
+
// Prevent body scroll while overlay is open
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const prev = document.body.style.overflow;
|
|
42
|
+
document.body.style.overflow = 'hidden';
|
|
43
|
+
return () => {
|
|
44
|
+
document.body.style.overflow = prev;
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
|
|
48
|
+
const handleWheel = useCallback((e: React.WheelEvent) => {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
const delta = e.deltaY > 0 ? -ZOOM_STEP : ZOOM_STEP;
|
|
51
|
+
setZoom((z) => clampZoom(z, delta));
|
|
52
|
+
}, []);
|
|
53
|
+
|
|
54
|
+
const handlePointerDown = useCallback(
|
|
55
|
+
(e: React.PointerEvent) => {
|
|
56
|
+
if (e.button !== 0) return;
|
|
57
|
+
setDragging(true);
|
|
58
|
+
dragStart.current = { x: e.clientX, y: e.clientY };
|
|
59
|
+
panStart.current = { ...pan };
|
|
60
|
+
(e.target as HTMLElement).setPointerCapture(e.pointerId);
|
|
61
|
+
},
|
|
62
|
+
[pan],
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const handlePointerMove = useCallback(
|
|
66
|
+
(e: React.PointerEvent) => {
|
|
67
|
+
if (!dragging) return;
|
|
68
|
+
const dx = e.clientX - dragStart.current.x;
|
|
69
|
+
const dy = e.clientY - dragStart.current.y;
|
|
70
|
+
setPan({ x: panStart.current.x + dx, y: panStart.current.y + dy });
|
|
71
|
+
},
|
|
72
|
+
[dragging],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const handlePointerUp = useCallback(() => {
|
|
76
|
+
setDragging(false);
|
|
77
|
+
}, []);
|
|
78
|
+
|
|
79
|
+
const resetView = useCallback(() => {
|
|
80
|
+
setZoom(1);
|
|
81
|
+
setPan({ x: 0, y: 0 });
|
|
82
|
+
}, []);
|
|
83
|
+
|
|
84
|
+
const zoomIn = useCallback(() => {
|
|
85
|
+
setZoom((z) => clampZoom(z, ZOOM_STEP));
|
|
86
|
+
}, []);
|
|
87
|
+
|
|
88
|
+
const zoomOut = useCallback(() => {
|
|
89
|
+
setZoom((z) => clampZoom(z, -ZOOM_STEP));
|
|
90
|
+
}, []);
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div className="fixed inset-0 z-[1000] flex flex-col bg-black/80 backdrop-blur-sm">
|
|
94
|
+
{/* Toolbar */}
|
|
95
|
+
<div className="flex items-center justify-between px-4 py-2 bg-surface/90 border-b border-edge">
|
|
96
|
+
<div className="flex items-center gap-2">
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
onClick={zoomOut}
|
|
100
|
+
className="p-1.5 rounded hover:bg-surface-raised text-content-secondary hover:text-content cursor-pointer"
|
|
101
|
+
aria-label="Zoom out"
|
|
102
|
+
>
|
|
103
|
+
<ZoomOut size={16} />
|
|
104
|
+
</button>
|
|
105
|
+
<span className="text-xs text-content-secondary font-mono min-w-[3.5rem] text-center">
|
|
106
|
+
{Math.round(zoom * 100)}%
|
|
107
|
+
</span>
|
|
108
|
+
<button
|
|
109
|
+
type="button"
|
|
110
|
+
onClick={zoomIn}
|
|
111
|
+
className="p-1.5 rounded hover:bg-surface-raised text-content-secondary hover:text-content cursor-pointer"
|
|
112
|
+
aria-label="Zoom in"
|
|
113
|
+
>
|
|
114
|
+
<ZoomIn size={16} />
|
|
115
|
+
</button>
|
|
116
|
+
<button
|
|
117
|
+
type="button"
|
|
118
|
+
onClick={resetView}
|
|
119
|
+
className="p-1.5 rounded hover:bg-surface-raised text-content-secondary hover:text-content cursor-pointer"
|
|
120
|
+
aria-label="Reset view"
|
|
121
|
+
>
|
|
122
|
+
<RotateCcw size={16} />
|
|
123
|
+
</button>
|
|
124
|
+
</div>
|
|
125
|
+
<button
|
|
126
|
+
type="button"
|
|
127
|
+
onClick={onClose}
|
|
128
|
+
className="p-1.5 rounded hover:bg-surface-raised text-content-secondary hover:text-content cursor-pointer"
|
|
129
|
+
aria-label="Close overlay"
|
|
130
|
+
>
|
|
131
|
+
<X size={18} />
|
|
132
|
+
</button>
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
{/* Diagram viewport */}
|
|
136
|
+
<div
|
|
137
|
+
ref={contentRef}
|
|
138
|
+
className="flex-1 overflow-hidden select-none"
|
|
139
|
+
style={{ cursor: dragging ? 'grabbing' : 'grab' }}
|
|
140
|
+
onWheel={handleWheel}
|
|
141
|
+
onPointerDown={handlePointerDown}
|
|
142
|
+
onPointerMove={handlePointerMove}
|
|
143
|
+
onPointerUp={handlePointerUp}
|
|
144
|
+
>
|
|
145
|
+
<div
|
|
146
|
+
className="w-full h-full flex items-center justify-center"
|
|
147
|
+
style={{
|
|
148
|
+
transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`,
|
|
149
|
+
transformOrigin: 'center center',
|
|
150
|
+
}}
|
|
151
|
+
>
|
|
152
|
+
<div
|
|
153
|
+
className="[&_svg]:max-w-none [&_svg]:h-auto"
|
|
154
|
+
dangerouslySetInnerHTML={{ __html: svgHtml }}
|
|
155
|
+
/>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
);
|
|
160
|
+
};
|
package/templates/assistkick-product-system/packages/frontend/src/components/EditorTabBar.tsx
CHANGED
|
@@ -31,19 +31,19 @@ export const EditorTabBar = ({ tabs, activeTabPath, dirtyPaths, onSelectTab, onC
|
|
|
31
31
|
if (tabs.length === 0) return null;
|
|
32
32
|
|
|
33
33
|
return (
|
|
34
|
-
<div className="
|
|
34
|
+
<div className="flex items-stretch h-[34px] bg-surface-alt border-b border-edge overflow-x-auto overflow-y-hidden shrink-0 [&::-webkit-scrollbar]:h-0">
|
|
35
35
|
{tabs.map((tab) => (
|
|
36
36
|
<button
|
|
37
37
|
key={tab.path}
|
|
38
|
-
className={`
|
|
38
|
+
className={`flex items-center gap-1.5 px-3 border-none border-r border-edge bg-transparent text-content-muted font-mono text-xs cursor-pointer whitespace-nowrap shrink-0 hover:text-content hover:bg-tab-hover ${tab.path === activeTabPath ? 'text-content bg-tab-active border-b-2 border-b-accent' : ''}`}
|
|
39
39
|
onClick={() => onSelectTab(tab.path)}
|
|
40
40
|
onMouseDown={(e) => handleMiddleClick(e, tab.path)}
|
|
41
41
|
title={tab.path}
|
|
42
42
|
>
|
|
43
|
-
{dirtyPaths.has(tab.path) && <span className="
|
|
44
|
-
<span className="
|
|
43
|
+
{dirtyPaths.has(tab.path) && <span className="text-accent-secondary text-[10px]">•</span>}
|
|
44
|
+
<span className="max-w-[150px] overflow-hidden text-ellipsis">{tab.name}</span>
|
|
45
45
|
<span
|
|
46
|
-
className="
|
|
46
|
+
className="inline-flex items-center justify-center w-4 h-4 rounded-sm opacity-50 cursor-pointer hover:opacity-100 hover:bg-white/10"
|
|
47
47
|
onClick={(e) => handleCloseClick(e, tab.path)}
|
|
48
48
|
role="button"
|
|
49
49
|
tabIndex={-1}
|
|
@@ -102,7 +102,7 @@ const FileTreeNode = ({
|
|
|
102
102
|
return (
|
|
103
103
|
<>
|
|
104
104
|
<button
|
|
105
|
-
className={`
|
|
105
|
+
className={`flex items-center gap-1 w-full h-[26px] border-none bg-transparent text-content-secondary font-mono text-xs cursor-pointer text-left whitespace-nowrap overflow-hidden text-ellipsis hover:bg-tab-hover hover:text-content ${isSelected ? 'bg-tab-active text-content' : ''}`}
|
|
106
106
|
style={{ paddingLeft: `${depth * 16 + 8}px` }}
|
|
107
107
|
onClick={handleClick}
|
|
108
108
|
onContextMenu={handleContextMenu}
|
|
@@ -110,21 +110,21 @@ const FileTreeNode = ({
|
|
|
110
110
|
>
|
|
111
111
|
{entry.type === 'directory' ? (
|
|
112
112
|
<>
|
|
113
|
-
<span className="
|
|
113
|
+
<span className="inline-flex items-center justify-center w-3.5 shrink-0">
|
|
114
114
|
{expanded ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
|
|
115
115
|
</span>
|
|
116
116
|
{expanded
|
|
117
|
-
? <FolderOpen size={ICON_SIZE} className="
|
|
118
|
-
: <Folder size={ICON_SIZE} className="
|
|
117
|
+
? <FolderOpen size={ICON_SIZE} className="shrink-0 text-accent" />
|
|
118
|
+
: <Folder size={ICON_SIZE} className="shrink-0 text-accent" />
|
|
119
119
|
}
|
|
120
120
|
</>
|
|
121
121
|
) : (
|
|
122
122
|
<>
|
|
123
|
-
<span className="
|
|
124
|
-
<File size={ICON_SIZE} className="
|
|
123
|
+
<span className="inline-flex items-center justify-center w-3.5 shrink-0 invisible" />
|
|
124
|
+
<File size={ICON_SIZE} className="shrink-0 text-content-muted" />
|
|
125
125
|
</>
|
|
126
126
|
)}
|
|
127
|
-
<span className="
|
|
127
|
+
<span className="overflow-hidden text-ellipsis">{entry.name}</span>
|
|
128
128
|
</button>
|
|
129
129
|
{entry.type === 'directory' && expanded && (
|
|
130
130
|
<>
|
|
@@ -233,7 +233,7 @@ export const FileTree = ({ tree, callbacks, selectedPath, expandedPaths, onToggl
|
|
|
233
233
|
|
|
234
234
|
const handleRootContextMenu = useCallback((e: React.MouseEvent) => {
|
|
235
235
|
// Only trigger if clicking on the empty area (not on a tree node)
|
|
236
|
-
if ((e.target as HTMLElement).closest('
|
|
236
|
+
if ((e.target as HTMLElement).closest('button')) return;
|
|
237
237
|
|
|
238
238
|
e.preventDefault();
|
|
239
239
|
setContextMenu({
|
|
@@ -272,7 +272,7 @@ export const FileTree = ({ tree, callbacks, selectedPath, expandedPaths, onToggl
|
|
|
272
272
|
const showRootCreateInput = inlineInput?.mode === 'create' && inlineInput.parentPath === '';
|
|
273
273
|
|
|
274
274
|
return (
|
|
275
|
-
<div className="
|
|
275
|
+
<div className="flex flex-col py-1 select-none min-h-full" ref={treeRef} onContextMenu={handleRootContextMenu}>
|
|
276
276
|
{showRootCreateInput && (
|
|
277
277
|
<FileTreeInlineInput
|
|
278
278
|
depth={0}
|
|
@@ -310,4 +310,3 @@ export const FileTree = ({ tree, callbacks, selectedPath, expandedPaths, onToggl
|
|
|
310
310
|
</div>
|
|
311
311
|
);
|
|
312
312
|
};
|
|
313
|
-
|
package/templates/assistkick-product-system/packages/frontend/src/components/FileTreeInlineInput.tsx
CHANGED
|
@@ -51,17 +51,17 @@ export const FileTreeInlineInput = ({ depth, initialValue, type, onSubmit, onCan
|
|
|
51
51
|
|
|
52
52
|
return (
|
|
53
53
|
<div
|
|
54
|
-
className="
|
|
54
|
+
className="flex items-center gap-1 h-[26px]"
|
|
55
55
|
style={{ paddingLeft: `${depth * 16 + 8}px` }}
|
|
56
56
|
>
|
|
57
|
-
<span className="
|
|
57
|
+
<span className="inline-flex items-center justify-center w-3.5 shrink-0 invisible" />
|
|
58
58
|
{type === 'directory'
|
|
59
|
-
? <Folder size={ICON_SIZE} className="
|
|
60
|
-
: <File size={ICON_SIZE} className="
|
|
59
|
+
? <Folder size={ICON_SIZE} className="shrink-0 text-accent" />
|
|
60
|
+
: <File size={ICON_SIZE} className="shrink-0 text-content-muted" />
|
|
61
61
|
}
|
|
62
62
|
<input
|
|
63
63
|
ref={inputRef}
|
|
64
|
-
className="
|
|
64
|
+
className="flex-1 min-w-0 h-5 px-1 border border-accent rounded-sm bg-surface text-content font-mono text-xs outline-none"
|
|
65
65
|
value={value}
|
|
66
66
|
onChange={(e) => setValue(e.target.value)}
|
|
67
67
|
onKeyDown={handleKeyDown}
|
|
@@ -2,6 +2,8 @@ import React, { useState, useEffect, useCallback, useRef } from 'react';
|
|
|
2
2
|
import Editor, { type OnMount } from '@monaco-editor/react';
|
|
3
3
|
import { FileTree } from './FileTree';
|
|
4
4
|
import { EditorTabBar } from './EditorTabBar';
|
|
5
|
+
import { UnifiedGitWidget } from './UnifiedGitWidget';
|
|
6
|
+
import { CommitMessageModal } from './CommitMessageModal';
|
|
5
7
|
import { useTheme } from '../hooks/useTheme';
|
|
6
8
|
import { useAutoSave } from '../hooks/useAutoSave';
|
|
7
9
|
import { apiClient } from '../api/client';
|
|
@@ -17,19 +19,9 @@ interface FilesViewProps {
|
|
|
17
19
|
projectId: string | null;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (entry.type === 'directory' && depth === 0) {
|
|
24
|
-
paths.add(entry.path);
|
|
25
|
-
}
|
|
26
|
-
if (entry.children) {
|
|
27
|
-
for (const p of collectExpandedPaths(entry.children, depth + 1)) {
|
|
28
|
-
paths.add(p);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return paths;
|
|
22
|
+
/** All directories start collapsed — returns an empty set. */
|
|
23
|
+
const collectExpandedPaths = (_tree: TreeEntry[], _depth: number): Set<string> => {
|
|
24
|
+
return new Set<string>();
|
|
33
25
|
};
|
|
34
26
|
|
|
35
27
|
export const FilesView = ({ projectId }: FilesViewProps) => {
|
|
@@ -45,6 +37,8 @@ export const FilesView = ({ projectId }: FilesViewProps) => {
|
|
|
45
37
|
const [treeError, setTreeError] = useState<string | null>(null);
|
|
46
38
|
const [treeWidth, setTreeWidth] = useState(DEFAULT_TREE_WIDTH);
|
|
47
39
|
const [expandedPaths, setExpandedPaths] = useState<Set<string>>(new Set());
|
|
40
|
+
const [commitModalOpen, setCommitModalOpen] = useState(false);
|
|
41
|
+
const [pendingBranch, setPendingBranch] = useState<string | null>(null);
|
|
48
42
|
const resizingRef = useRef(false);
|
|
49
43
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
50
44
|
const initialExpandDone = useRef(false);
|
|
@@ -79,6 +73,60 @@ export const FilesView = ({ projectId }: FilesViewProps) => {
|
|
|
79
73
|
loadTree();
|
|
80
74
|
}, [loadTree]);
|
|
81
75
|
|
|
76
|
+
// After a branch switch, reload the tree and reconcile open tabs
|
|
77
|
+
const handleBranchSwitch = useCallback(async () => {
|
|
78
|
+
if (!projectId) return;
|
|
79
|
+
initialExpandDone.current = false;
|
|
80
|
+
await loadTree();
|
|
81
|
+
|
|
82
|
+
// Reload open tabs — close those whose files no longer exist on the new branch
|
|
83
|
+
const newFileContents: Record<string, string> = {};
|
|
84
|
+
const survivingTabs: EditorTab[] = [];
|
|
85
|
+
|
|
86
|
+
for (const tab of tabs) {
|
|
87
|
+
try {
|
|
88
|
+
const data = await apiClient.fetchFileContent(projectId, tab.path);
|
|
89
|
+
if (data.binary) {
|
|
90
|
+
newFileContents[tab.path] = `[Binary file — ${data.size} bytes]`;
|
|
91
|
+
} else {
|
|
92
|
+
newFileContents[tab.path] = data.content;
|
|
93
|
+
}
|
|
94
|
+
survivingTabs.push(tab);
|
|
95
|
+
} catch {
|
|
96
|
+
// File doesn't exist on new branch — drop this tab
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
setTabs(survivingTabs);
|
|
101
|
+
setFileContents(newFileContents);
|
|
102
|
+
|
|
103
|
+
if (activeTabPath && !survivingTabs.find(t => t.path === activeTabPath)) {
|
|
104
|
+
setActiveTabPath(survivingTabs.length > 0 ? survivingTabs[0].path : null);
|
|
105
|
+
}
|
|
106
|
+
}, [projectId, loadTree, tabs, activeTabPath]);
|
|
107
|
+
|
|
108
|
+
const handleDirtyCheckout = useCallback((branch: string) => {
|
|
109
|
+
setPendingBranch(branch);
|
|
110
|
+
setCommitModalOpen(true);
|
|
111
|
+
}, []);
|
|
112
|
+
|
|
113
|
+
const handleCommitAndSwitch = useCallback(async (message: string) => {
|
|
114
|
+
if (!projectId || !pendingBranch) return;
|
|
115
|
+
setCommitModalOpen(false);
|
|
116
|
+
try {
|
|
117
|
+
await apiClient.checkoutBranch(projectId, pendingBranch, message);
|
|
118
|
+
setPendingBranch(null);
|
|
119
|
+
handleBranchSwitch();
|
|
120
|
+
} catch (err: any) {
|
|
121
|
+
console.error('Failed to commit and switch:', err);
|
|
122
|
+
}
|
|
123
|
+
}, [projectId, pendingBranch, handleBranchSwitch]);
|
|
124
|
+
|
|
125
|
+
const handleCommitModalCancel = useCallback(() => {
|
|
126
|
+
setCommitModalOpen(false);
|
|
127
|
+
setPendingBranch(null);
|
|
128
|
+
}, []);
|
|
129
|
+
|
|
82
130
|
const handleToggleExpand = useCallback((path: string) => {
|
|
83
131
|
setExpandedPaths((prev) => {
|
|
84
132
|
const next = new Set(prev);
|
|
@@ -316,7 +364,7 @@ export const FilesView = ({ projectId }: FilesViewProps) => {
|
|
|
316
364
|
// No project selected
|
|
317
365
|
if (!projectId) {
|
|
318
366
|
return (
|
|
319
|
-
<div className="
|
|
367
|
+
<div className="flex items-center justify-center h-full w-full">
|
|
320
368
|
<p className="text-content-muted">Select a project to browse files</p>
|
|
321
369
|
</div>
|
|
322
370
|
);
|
|
@@ -325,7 +373,7 @@ export const FilesView = ({ projectId }: FilesViewProps) => {
|
|
|
325
373
|
// Workspace error (no git repo connected)
|
|
326
374
|
if (treeError) {
|
|
327
375
|
return (
|
|
328
|
-
<div className="
|
|
376
|
+
<div className="flex items-center justify-center h-full w-full">
|
|
329
377
|
<p className="text-content-muted">{treeError}</p>
|
|
330
378
|
</div>
|
|
331
379
|
);
|
|
@@ -335,13 +383,29 @@ export const FilesView = ({ projectId }: FilesViewProps) => {
|
|
|
335
383
|
const activeContent = activeTabPath ? (fileContents[activeTabPath] ?? '') : '';
|
|
336
384
|
|
|
337
385
|
return (
|
|
338
|
-
<div className="
|
|
386
|
+
<div className="flex w-full h-full overflow-hidden" ref={containerRef}>
|
|
387
|
+
{/* Commit message modal for dirty branch switching */}
|
|
388
|
+
<CommitMessageModal
|
|
389
|
+
isOpen={commitModalOpen}
|
|
390
|
+
targetBranch={pendingBranch || ''}
|
|
391
|
+
onConfirm={handleCommitAndSwitch}
|
|
392
|
+
onCancel={handleCommitModalCancel}
|
|
393
|
+
/>
|
|
394
|
+
|
|
339
395
|
{/* File tree sidebar */}
|
|
340
|
-
<div
|
|
341
|
-
|
|
396
|
+
<div
|
|
397
|
+
className="flex flex-col h-full overflow-hidden border-r border-edge bg-surface-alt shrink-0"
|
|
398
|
+
style={{ width: `${treeWidth}px`, minWidth: `${treeWidth}px` }}
|
|
399
|
+
>
|
|
400
|
+
<UnifiedGitWidget
|
|
401
|
+
projectId={projectId}
|
|
402
|
+
onBranchSwitch={handleBranchSwitch}
|
|
403
|
+
onDirtyCheckout={handleDirtyCheckout}
|
|
404
|
+
/>
|
|
405
|
+
<div className="px-3 pt-2 pb-1 select-none">
|
|
342
406
|
<span className="text-[11px] uppercase tracking-wider font-medium text-content-muted">Explorer</span>
|
|
343
407
|
</div>
|
|
344
|
-
<div className="
|
|
408
|
+
<div className="flex-1 overflow-y-auto overflow-x-hidden">
|
|
345
409
|
{tree.length === 0 ? (
|
|
346
410
|
<p className="text-content-muted text-xs p-3">No files found</p>
|
|
347
411
|
) : (
|
|
@@ -357,10 +421,13 @@ export const FilesView = ({ projectId }: FilesViewProps) => {
|
|
|
357
421
|
</div>
|
|
358
422
|
|
|
359
423
|
{/* Resize handle */}
|
|
360
|
-
<div
|
|
424
|
+
<div
|
|
425
|
+
className="w-1 shrink-0 cursor-col-resize transition-colors hover:bg-accent active:bg-accent"
|
|
426
|
+
onMouseDown={handleResizeStart}
|
|
427
|
+
/>
|
|
361
428
|
|
|
362
429
|
{/* Editor area */}
|
|
363
|
-
<div className="
|
|
430
|
+
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
|
364
431
|
<EditorTabBar
|
|
365
432
|
tabs={tabs}
|
|
366
433
|
activeTabPath={activeTabPath}
|
|
@@ -369,32 +436,36 @@ export const FilesView = ({ projectId }: FilesViewProps) => {
|
|
|
369
436
|
onCloseTab={handleCloseTab}
|
|
370
437
|
/>
|
|
371
438
|
{activeTab ? (
|
|
372
|
-
<div className="
|
|
439
|
+
<div className="flex-1 relative overflow-hidden">
|
|
373
440
|
{loading && (
|
|
374
|
-
<div className="
|
|
441
|
+
<div className="absolute inset-0 flex items-center justify-center bg-surface opacity-70 z-5">
|
|
375
442
|
<span className="text-content-muted text-sm">Loading...</span>
|
|
376
443
|
</div>
|
|
377
444
|
)}
|
|
378
|
-
<
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
445
|
+
<div className="absolute inset-0">
|
|
446
|
+
<Editor
|
|
447
|
+
width="100%"
|
|
448
|
+
height="100%"
|
|
449
|
+
language={activeTab.language}
|
|
450
|
+
value={activeContent}
|
|
451
|
+
theme={theme === 'dark' ? 'vs-dark' : 'vs'}
|
|
452
|
+
path={activeTab.path}
|
|
453
|
+
onChange={handleEditorChange}
|
|
454
|
+
onMount={handleEditorMount}
|
|
455
|
+
options={{
|
|
456
|
+
minimap: { enabled: true },
|
|
457
|
+
fontSize: 13,
|
|
458
|
+
lineNumbers: 'on',
|
|
459
|
+
scrollBeyondLastLine: false,
|
|
460
|
+
automaticLayout: true,
|
|
461
|
+
tabSize: 2,
|
|
462
|
+
wordWrap: 'off',
|
|
463
|
+
}}
|
|
464
|
+
/>
|
|
465
|
+
</div>
|
|
395
466
|
</div>
|
|
396
467
|
) : (
|
|
397
|
-
<div className="
|
|
468
|
+
<div className="flex-1 flex items-center justify-center w-full">
|
|
398
469
|
<p className="text-content-muted text-sm">Open a file from the explorer to start editing</p>
|
|
399
470
|
</div>
|
|
400
471
|
)}
|
package/templates/assistkick-product-system/packages/frontend/src/components/GraphLegend.tsx
CHANGED
|
@@ -72,9 +72,9 @@ export function GraphLegend({ visible, onTypeToggle, onSearchChange }: GraphLege
|
|
|
72
72
|
<div className="mt-2 first:mt-0">
|
|
73
73
|
<div className="text-[10px] text-content-muted uppercase tracking-wider mb-1">Node Size</div>
|
|
74
74
|
<div className="flex items-center gap-1.5">
|
|
75
|
-
<span className="w-2 h-2 rounded-full
|
|
75
|
+
<span className="w-2 h-2 rounded-full bg-content-muted" />
|
|
76
76
|
<span className="text-[10px] text-content-muted">{'\u2192'}</span>
|
|
77
|
-
<span className="w-[18px] h-[18px] rounded-full
|
|
77
|
+
<span className="w-[18px] h-[18px] rounded-full bg-content-muted" />
|
|
78
78
|
<span className="text-[11px] text-content-secondary whitespace-nowrap">more connections = larger</span>
|
|
79
79
|
</div>
|
|
80
80
|
</div>
|