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

@@ -15,6 +15,7 @@ import { nodeTypes } from './nodes/nodeTypes'
import { edgeTypes } from './edges/edgeTypes'
import { getDeviceRenderConfig } from './nodes/deviceRegistry'
import type { DeviceNodeData } from './nodes/DeviceNode'
import type { InteractionMode } from './DiagramHeader'
interface NetworkCanvasProps {
nodes: Node[]
@@ -31,6 +32,7 @@ interface NetworkCanvasProps {
onNodeContextMenu?: (event: React.MouseEvent, node: Node) => void
onPaneContextMenu?: (event: MouseEvent | React.MouseEvent) => void
onPaneClick?: () => void
interactionMode?: InteractionMode
}
export function NetworkCanvas({
@@ -48,6 +50,7 @@ export function NetworkCanvas({
onNodeContextMenu,
onPaneContextMenu,
onPaneClick: onPaneClickProp,
interactionMode = 'select',
}: NetworkCanvasProps) {
const handleSelectionChange = useCallback(({ nodes: selectedNodes, edges: selectedEdges }: { nodes: Node[]; edges: Edge[] }) => {
if (selectedNodes.length === 1) {
@@ -93,10 +96,13 @@ export function NetworkCanvas({
defaultEdgeOptions={{ type: 'connection' }}
deleteKeyCode={['Backspace', 'Delete']}
multiSelectionKeyCode="Shift"
panOnDrag={interactionMode === 'pan'}
selectionOnDrag={interactionMode === 'select'}
panActivationKeyCode="Space"
snapToGrid={true}
snapGrid={[20, 20]}
fitView
className="bg-page"
className={interactionMode === 'pan' ? 'bg-page cursor-grab active:cursor-grabbing' : 'bg-page'}
>
<Background variant={BackgroundVariant.Dots} color="var(--color-border-default)" gap={20} size={1} />
<Controls className="!border-default !bg-card [&>button]:!border-default [&>button]:!bg-card [&>button]:!fill-text-primary" />