fix(core): prevent multi touch from aborting connections (#1938)

* fix(core): prevent multi touch from aborting connections

Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>

* chore(changeset): add

---------

Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
Braks
2025-08-31 13:51:20 +02:00
parent c9c26d02f6
commit 490473d997
3 changed files with 24 additions and 6 deletions

View File

@@ -0,0 +1,5 @@
---
"@vue-flow/core": patch
---
Prevent multi touch from aborting connections.

View File

@@ -278,6 +278,11 @@ export function useHandle({
}
function onPointerUp(event: MouseTouchEvent) {
// Prevent multi-touch aborting connection
if ('touches' in event && event.touches.length > 0) {
return
}
if ((closestHandle || handleDomNode) && connection && isValid) {
if (!onEdgeUpdate) {
emits.connect(connection)

View File

@@ -76,6 +76,8 @@ const shouldPanOnScroll = toRef(() => panKeyPressed.value || panOnScroll.value)
const isSelecting = toRef(() => selectionKeyPressed.value || (selectionKeyCode.value === true && shouldPanOnDrag.value !== true))
const connectionInProgress = toRef(() => connectionStartHandle.value !== null)
onMounted(() => {
if (!viewportRef.value) {
warn('Viewport element is missing')
@@ -163,6 +165,7 @@ onMounted(() => {
const zoomScroll = zoomKeyPressed.value || zoomOnScroll.value
const pinchZoom = zoomOnPinch.value && event.ctrlKey
const eventButton = (event as MouseEvent).button
const isWheelEvent = event.type === 'wheel'
if (
eventButton === 1 &&
@@ -182,30 +185,35 @@ onMounted(() => {
return false
}
// we want to disable pinch-zooming while making a connection
if (connectionInProgress.value && !isWheelEvent) {
return false
}
// if zoom on double click is disabled, we prevent the double click event
if (!zoomOnDoubleClick.value && event.type === 'dblclick') {
return false
}
// if the target element is inside an element with the nowheel class, we prevent zooming
if (isWrappedWithClass(event, noWheelClassName.value) && event.type === 'wheel') {
if (isWrappedWithClass(event, noWheelClassName.value) && isWheelEvent) {
return false
}
// if the target element is inside an element with the nopan class, we prevent panning
if (
isWrappedWithClass(event, noPanClassName.value) &&
(event.type !== 'wheel' || (shouldPanOnScroll.value && event.type === 'wheel' && !zoomKeyPressed.value))
(!isWheelEvent || (shouldPanOnScroll.value && isWheelEvent && !zoomKeyPressed.value))
) {
return false
}
if (!zoomOnPinch.value && event.ctrlKey && event.type === 'wheel') {
if (!zoomOnPinch.value && event.ctrlKey && isWheelEvent) {
return false
}
// when there is no scroll handling enabled, we prevent all wheel events
if (!zoomScroll && !shouldPanOnScroll.value && !pinchZoom && event.type === 'wheel') {
if (!zoomScroll && !shouldPanOnScroll.value && !pinchZoom && isWheelEvent) {
return false
}
@@ -242,7 +250,7 @@ onMounted(() => {
eventButton <= 1
// default filter for d3-zoom
return (!event.ctrlKey || panKeyPressed.value || event.type === 'wheel') && buttonAllowed
return (!event.ctrlKey || panKeyPressed.value || isWheelEvent) && buttonAllowed
})
watch(
@@ -414,7 +422,7 @@ export default {
:is-selecting="isSelecting"
:selection-key-pressed="selectionKeyPressed"
:class="{
connecting: !!connectionStartHandle,
connecting: connectionInProgress,
dragging: paneDragging,
draggable: panOnDrag === true || (Array.isArray(panOnDrag) && panOnDrag.includes(0)),
}"