feat(canvas): enhance canvas toolbar for mode switching and improve selection box behavior

This commit is contained in:
HouYunFei
2026-08-06 15:00:01 +08:00
parent 4272b8e1b7
commit 3a9ca04ad0
10 changed files with 63 additions and 43 deletions
+9 -13
View File
@@ -199,6 +199,7 @@ function InfiniteCanvasPage() {
const [chatSessions, setChatSessions] = useState<CanvasAssistantSession[]>([]);
const [activeChatId, setActiveChatId] = useState<string | null>(null);
const [viewport, setViewport] = useState<ViewportTransform>({ x: 0, y: 0, k: 1 });
const [canvasTool, setCanvasTool] = useState<"select" | "pan">("select");
const [size, setSize] = useState({ width: 1200, height: 720 });
const [selectedNodeIds, setSelectedNodeIds] = useState<Set<string>>(new Set());
const [selectedConnectionId, setSelectedConnectionId] = useState<string | null>(null);
@@ -977,13 +978,6 @@ function InfiniteCanvasPage() {
if (pendingConnectionCreateRef.current) cancelPendingConnectionCreate();
if (event.button !== 0) return;
if (!event.ctrlKey && !event.metaKey) {
setSelectionBox(null);
setSelectedNodeIds(new Set());
setSelectedConnectionId(null);
return;
}
const world = screenToCanvas(event.clientX, event.clientY);
const nextSelectionBox = {
startWorldX: world.x,
@@ -2775,6 +2769,7 @@ function InfiniteCanvasPage() {
<InfiniteCanvas
containerRef={containerRef}
viewport={viewport}
tool={canvasTool}
backgroundMode={backgroundMode}
onViewportChange={(next) => {
setViewport(next);
@@ -2863,17 +2858,17 @@ function InfiniteCanvasPage() {
))}
{selectionBox ? (
<div
className="pointer-events-none absolute z-[100] border"
<svg
className="pointer-events-none absolute z-[100] overflow-visible"
style={{
left: Math.min(selectionBox.startWorldX, selectionBox.currentWorldX),
top: Math.min(selectionBox.startWorldY, selectionBox.currentWorldY),
width: Math.abs(selectionBox.currentWorldX - selectionBox.startWorldX),
height: Math.abs(selectionBox.currentWorldY - selectionBox.startWorldY),
borderColor: theme.canvas.selectionStroke,
background: theme.canvas.selectionFill,
}}
/>
>
<rect width="100%" height="100%" fill={theme.canvas.selectionFill} stroke={theme.canvas.selectionStroke} strokeWidth={1.5 / viewport.k} strokeDasharray={`${10 / viewport.k} ${6 / viewport.k}`} />
</svg>
) : null}
{pendingConnectionCreate ? <ConnectionCreateMenu pending={pendingConnectionCreate} onCreate={(type) => createConnectedNode(type, pendingConnectionCreate)} onClose={cancelPendingConnectionCreate} /> : null}
{nodeCreatePosition ? (
@@ -2918,6 +2913,7 @@ function InfiniteCanvasPage() {
<CanvasToolbar
selectedCount={selectedNodeIds.size}
canvasTool={canvasTool}
canUndo={historyState.canUndo}
canRedo={historyState.canRedo}
backgroundMode={backgroundMode}
@@ -2934,7 +2930,7 @@ function InfiniteCanvasPage() {
onUpload={() => handleUploadRequest()}
onDelete={() => deleteNodes(new Set(selectedNodeIds))}
onClear={() => setClearConfirmOpen(true)}
onDeselect={deselectCanvas}
onCanvasToolChange={setCanvasTool}
onBackgroundModeChange={setBackgroundMode}
onShowImageInfoChange={setShowImageInfo}
/>