11<script lang="ts" setup>
2- import { ref , toRef } from ' vue'
2+ import { ref , toRef , watch } from ' vue'
33import UserSelection from ' ../../components/UserSelection/UserSelection.vue'
44import NodesSelection from ' ../../components/NodesSelection/NodesSelection.vue'
5- import type { GraphNode } from ' ../../types'
6- import { SelectionMode } from ' ../../types'
5+ import { type GraphNode , SelectionMode } from ' ../../types'
76import { useKeyPress , useVueFlow } from ' ../../composables'
87import { getConnectedEdges , getNodesInside } from ' ../../utils'
98import { getMousePosition } from ' ./utils'
109
11- const { isSelecting } = defineProps <{ isSelecting: boolean }>()
10+ const { isSelecting, selectionKeyPressed } = defineProps <{ isSelecting: boolean ; selectionKeyPressed : boolean }>()
1211
1312const {
1413 vueFlowRef,
@@ -43,41 +42,44 @@ const containerBounds = ref<DOMRect>()
4342
4443const hasActiveSelection = toRef (() => elementsSelectable .value && (isSelecting || userSelectionActive .value ))
4544
46- useKeyPress (
47- deleteKeyCode ,
48- (keyPressed ) => {
49- if (! keyPressed ) {
50- return
51- }
45+ // Used to prevent click events when the user lets go of the selectionKey during a selection
46+ const selectionInProgress = ref (false )
5247
53- const nodesToRemove: GraphNode [] = []
54- for (const node of getNodes .value ) {
55- if (! node .selected && node .parentNode && nodesToRemove .some ((n ) => n .id === node .parentNode )) {
56- nodesToRemove .push (node )
57- } else if (node .selected ) {
58- nodesToRemove .push (node )
59- }
60- }
48+ const deleteKeyPressed = useKeyPress (deleteKeyCode , { actInsideInputWithModifier: false })
6149
62- if (nodesToRemove || getSelectedEdges .value ) {
63- if (getSelectedEdges .value .length > 0 ) {
64- removeEdges (getSelectedEdges .value )
65- }
50+ const multiSelectKeyPressed = useKeyPress (multiSelectionKeyCode )
6651
67- if (nodesToRemove .length > 0 ) {
68- removeNodes (nodesToRemove )
69- }
52+ watch (deleteKeyPressed , (isKeyPressed ) => {
53+ if (! isKeyPressed ) {
54+ return
55+ }
56+
57+ const nodesToRemove: GraphNode [] = []
58+ for (const node of getNodes .value ) {
59+ if (! node .selected && node .parentNode && nodesToRemove .some ((n ) => n .id === node .parentNode )) {
60+ nodesToRemove .push (node )
61+ } else if (node .selected ) {
62+ nodesToRemove .push (node )
63+ }
64+ }
7065
71- nodesSelectionActive .value = false
66+ if (nodesToRemove || getSelectedEdges .value ) {
67+ if (getSelectedEdges .value .length > 0 ) {
68+ removeEdges (getSelectedEdges .value )
69+ }
7270
73- removeSelectedElements ()
71+ if (nodesToRemove .length > 0 ) {
72+ removeNodes (nodesToRemove )
7473 }
75- },
76- { actInsideInputWithModifier: false },
77- )
7874
79- useKeyPress (multiSelectionKeyCode , (keyPressed ) => {
80- multiSelectionActive .value = keyPressed
75+ nodesSelectionActive .value = false
76+
77+ removeSelectedElements ()
78+ }
79+ })
80+
81+ watch (multiSelectKeyPressed , (isKeyPressed ) => {
82+ multiSelectionActive .value = isKeyPressed
8183})
8284
8385function resetUserSelection() {
@@ -89,7 +91,8 @@ function resetUserSelection() {
8991}
9092
9193function onClick(event : MouseEvent ) {
92- if (event .target !== container .value || hasActiveSelection .value ) {
94+ if (selectionInProgress .value || event .target !== container .value || hasActiveSelection .value ) {
95+ selectionInProgress .value = false
9396 return
9497 }
9598
@@ -121,8 +124,9 @@ function onWheel(event: WheelEvent) {
121124 emits .paneScroll (event )
122125}
123126
124- function onMouseDown(event : MouseEvent ) {
125- containerBounds .value = vueFlowRef .value ! .getBoundingClientRect ()
127+ function onPointerDown(event : PointerEvent ) {
128+ containerBounds .value = vueFlowRef .value ?.getBoundingClientRect ()
129+ container .value ?.setPointerCapture (event .pointerId )
126130
127131 if (
128132 ! hasActiveSelection .value ||
@@ -153,26 +157,19 @@ function onMouseDown(event: MouseEvent) {
153157 emits .selectionStart (event )
154158}
155159
156- function onMouseMove (event : MouseEvent ) {
160+ function onPointerMove (event : PointerEvent ) {
157161 if (! hasActiveSelection .value ) {
158162 return emits .paneMouseMove (event )
159163 }
160164
161- if (! isSelecting || ! containerBounds .value || ! userSelectionRect .value ) {
165+ if (! containerBounds .value || ! userSelectionRect .value ) {
162166 return
163167 }
164168
165- if (! userSelectionActive .value ) {
166- userSelectionActive .value = true
167- }
168-
169- if (nodesSelectionActive .value ) {
170- nodesSelectionActive .value = false
171- }
169+ selectionInProgress .value = true
172170
173171 const mousePos = getMousePosition (event , containerBounds .value )
174- const startX = userSelectionRect .value .startX ?? 0
175- const startY = userSelectionRect .value .startY ?? 0
172+ const { startX = 0 , startY = 0 } = userSelectionRect .value
176173
177174 const nextUserSelectRect = {
178175 ... userSelectionRect .value ,
@@ -187,6 +184,7 @@ function onMouseMove(event: MouseEvent) {
187184 userSelectionRect .value ,
188185 viewport .value ,
189186 selectionMode .value === SelectionMode .Partial ,
187+ true ,
190188 )
191189
192190 const selectedEdges = getConnectedEdges (selectedNodes , getEdges .value )
@@ -199,14 +197,12 @@ function onMouseMove(event: MouseEvent) {
199197 addSelectedElements ([... selectedNodes , ... selectedEdges ])
200198}
201199
202- function onMouseUp (event : MouseEvent ) {
203- if (! hasActiveSelection .value ) {
200+ function onPointerUp (event : PointerEvent ) {
201+ if (! hasActiveSelection .value || event . button !== 0 ) {
204202 return
205203 }
206204
207- if (event .button !== 0 ) {
208- return
209- }
205+ container .value ?.releasePointerCapture (event .pointerId )
210206
211207 // We only want to trigger click functions when in selection mode if
212208 // the user did not move the mouse.
@@ -219,22 +215,15 @@ function onMouseUp(event: MouseEvent) {
219215 resetUserSelection ()
220216
221217 emits .selectionEnd (event )
222- }
223-
224- function onMouseLeave(event : MouseEvent ) {
225- if (! hasActiveSelection .value ) {
226- return emits .paneMouseLeave (event )
227- }
228218
229- if (userSelectionActive .value ) {
230- nodesSelectionActive .value = prevSelectedNodesCount .value > 0
231- emits .selectionEnd ?.(event )
219+ // If the user kept holding the selectionKey during the selection,
220+ // we need to reset the selectionInProgress, so the next click event is not prevented
221+ if (selectionKeyPressed ) {
222+ selectionInProgress .value = false
232223 }
233-
234- resetUserSelection ()
235224}
236225
237- function onMouseEnter (event : MouseEvent ) {
226+ function onPointerEnter (event : PointerEvent ) {
238227 if (hasActiveSelection .value ) {
239228 return
240229 }
@@ -258,11 +247,10 @@ export default {
258247 @click =" onClick"
259248 @contextmenu =" onContextMenu"
260249 @wheel.passive =" onWheel"
261- @mouseenter =" onMouseEnter"
262- @mousedown =" onMouseDown"
263- @mousemove =" onMouseMove"
264- @mouseup =" onMouseUp"
265- @mouseleave =" onMouseLeave"
250+ @pointerenter =" onPointerEnter"
251+ @pointerdown =" onPointerDown"
252+ @pointermove =" onPointerMove"
253+ @pointerup =" onPointerUp"
266254 >
267255 <slot />
268256 <UserSelection v-if =" userSelectionActive && userSelectionRect" :user-selection-rect =" userSelectionRect" />
0 commit comments