feat(network): add pointer/hand mode toggle to diagram toolbar

- Header shows MousePointer2 (select) and Hand (pan) toggle buttons
- Select mode: drag on canvas draws a selection box (selectionOnDrag)
- Pan mode: drag on canvas pans the viewport (panOnDrag)
- Space held in either mode temporarily switches to pan (panActivationKeyCode)
- Keyboard shortcuts: V = select mode, H = pan mode
- Cursor changes to grab/grabbing in pan mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-04-14 00:38:51 +00:00
parent 4a12c9b37d
commit 684fb07e47
4 changed files with 65 additions and 4 deletions

View File

@@ -1,6 +1,9 @@
import { useState, useCallback, useRef, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { ChevronLeft, Save, Download, FileJson, Image, FileText, Undo2, Redo2 } from 'lucide-react'
import { ChevronLeft, Save, Download, FileJson, Image, FileText, Undo2, Redo2, MousePointer2, Hand } from 'lucide-react'
import { cn } from '@/lib/utils'
export type InteractionMode = 'select' | 'pan'
interface DiagramHeaderProps {
name: string
@@ -18,6 +21,8 @@ interface DiagramHeaderProps {
onRedo: () => void
canUndo: boolean
canRedo: boolean
interactionMode: InteractionMode
onModeChange: (mode: InteractionMode) => void
}
export function DiagramHeader({
@@ -36,6 +41,8 @@ export function DiagramHeader({
onRedo,
canUndo,
canRedo,
interactionMode,
onModeChange,
}: DiagramHeaderProps) {
const navigate = useNavigate()
const [editing, setEditing] = useState(false)
@@ -117,6 +124,36 @@ export function DiagramHeader({
<div className="mx-2 h-5 w-px bg-border-default" />
{/* Interaction mode toggle */}
<div className="flex items-center rounded border border-default overflow-hidden">
<button
onClick={() => onModeChange('select')}
title="Select (V)"
className={cn(
'p-1.5 transition-colors',
interactionMode === 'select'
? 'bg-elevated text-primary'
: 'text-muted-foreground hover:text-primary hover:bg-elevated/50',
)}
>
<MousePointer2 size={15} />
</button>
<button
onClick={() => onModeChange('pan')}
title="Pan (H)"
className={cn(
'p-1.5 transition-colors',
interactionMode === 'pan'
? 'bg-elevated text-primary'
: 'text-muted-foreground hover:text-primary hover:bg-elevated/50',
)}
>
<Hand size={15} />
</button>
</div>
<div className="mx-2 h-5 w-px bg-border-default" />
{editing ? (
<input
ref={inputRef}