@@ -44,6 +44,7 @@ import {
4444import { diagramNodeTypes } from "./nodes"
4545import { useDiagramModifiable } from "./hooks/useDiagramModifiable"
4646import { useKeyboardShortcuts } from "./hooks/useKeyboardShortcuts"
47+ import { useMultiSelectionMode } from "./hooks/useMultiSelectionMode"
4748import { usePaneClicked } from "./hooks/usePaneClicked"
4849import {
4950 useRemoteDraggingNodes ,
@@ -144,6 +145,7 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
144145 const { onBeforeDelete, onNodeDoubleClick, onEdgeDoubleClick } =
145146 useElementInteractions ( )
146147 const { onPaneClicked } = usePaneClicked ( )
148+ const multiSelectionMode = useMultiSelectionMode ( )
147149
148150 const handleReactFlowInit = useCallback (
149151 ( instance : ReactFlowInstance ) => {
@@ -245,13 +247,22 @@ function App({ onReactFlowInit, collaboration, awareness }: AppProps) {
245247 nodesDraggable = { isDiagramModifiable }
246248 panOnScroll = { ! scrollLock || scrollEnabled }
247249 zoomOnScroll = { ! scrollLock || scrollEnabled }
248- // Keep the default left-drag pan (panOnDrag=true) — we do NOT switch
249- // to selectionOnDrag/space-pan. Adding Shift to multiSelectionKeyCode
250- // makes Shift+CLICK on a node/edge toggle it in/out of the
251- // multi-selection. selectionKeyCode keeps its default (Shift), so a
252- // Shift+DRAG on the empty pane still box-selects — no conflict, since
253- // a click on a node and a drag on the pane are different surfaces.
250+ // Shift is also selectionKeyCode's default, but there's no conflict:
251+ // a click on a node and a Shift+drag on the pane are different
252+ // surfaces.
254253 multiSelectionKeyCode = { [ "Shift" , "Meta" , "Control" ] }
254+ // With multiSelectionActive forced on, React Flow's pointerdown
255+ // select would toggle the pressed node OUT of the selection and drop
256+ // it from the group drag; selecting on click keeps the group whole.
257+ selectNodesOnDrag = { ! multiSelectionMode }
258+ // In the mode, a plain left-drag on the pane draws a selection box;
259+ // panning moves to middle/right-drag (scroll/trackpad already pans
260+ // by default). This is mouse-only by construction: d3-zoom gates the
261+ // pan buttons on `mousedown` alone, so a touch drag ignores the [1,2]
262+ // gate and keeps panning through the separate touch handler — which
263+ // is why a one-finger drag never box-selects and pinch-zoom survives.
264+ selectionOnDrag = { multiSelectionMode }
265+ panOnDrag = { multiSelectionMode ? [ 1 , 2 ] : true }
255266 // Delete the current selection with either key (Backspace on macOS,
256267 // Delete on full keyboards).
257268 deleteKeyCode = { [ "Backspace" , "Delete" ] }
0 commit comments