[fix] do not drag on right-click + fix refs (#5784)

## Summary

Fixes drag handling logic.

## Changes

Only check for drag on left-click.

Adds handler logic for following pointer events:
1. drag termination
2. context menu
3. pointer cancel

Adds tests.

Consolidates cleanup tasks.

## Screenshots

Fixed State:

Ignore first failed drag, browser window didn't have context.


https://github.com/user-attachments/assets/00ec685a-1ef7-4102-b19b-4cdb9b201d22

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5784-fix-do-not-drag-on-right-click-fix-refs-27a6d73d3650812ea797fccf14022568)
by [Unito](https://www.unito.io)
This commit is contained in:
Arjan Singh
2025-09-26 12:05:36 -07:00
committed by GitHub
parent c96f719f91
commit 62441fa0f9
4 changed files with 344 additions and 41 deletions

View File

@@ -4,6 +4,7 @@ import {
type MaybeRefOrGetter,
computed,
inject,
ref,
toValue
} from 'vue'
@@ -50,7 +51,7 @@ export function useNodeLayout(nodeIdMaybe: MaybeRefOrGetter<string>) {
const zIndex = computed(() => layoutRef.value?.zIndex ?? 0)
// Drag state
let isDragging = false
const isDragging = ref(false)
let dragStartPos: Point | null = null
let dragStartMouse: Point | null = null
let otherSelectedNodesStartPositions: Map<string, Point> | null = null
@@ -59,9 +60,9 @@ export function useNodeLayout(nodeIdMaybe: MaybeRefOrGetter<string>) {
* Start dragging the node
*/
function startDrag(event: PointerEvent) {
if (!layoutRef.value) return
if (!layoutRef.value || !transformState) return
isDragging = true
isDragging.value = true
dragStartPos = { ...position.value }
dragStartMouse = { x: event.clientX, y: event.clientY }
@@ -87,15 +88,20 @@ export function useNodeLayout(nodeIdMaybe: MaybeRefOrGetter<string>) {
mutations.setSource(LayoutSource.Vue)
// Capture pointer
const target = event.target as HTMLElement
target.setPointerCapture(event.pointerId)
if (!(event.target instanceof HTMLElement)) return
event.target.setPointerCapture(event.pointerId)
}
/**
* Handle drag movement
*/
const handleDrag = (event: PointerEvent) => {
if (!isDragging || !dragStartPos || !dragStartMouse || !transformState) {
if (
!isDragging.value ||
!dragStartPos ||
!dragStartMouse ||
!transformState
) {
return
}
@@ -141,16 +147,16 @@ export function useNodeLayout(nodeIdMaybe: MaybeRefOrGetter<string>) {
* End dragging
*/
function endDrag(event: PointerEvent) {
if (!isDragging) return
if (!isDragging.value) return
isDragging = false
isDragging.value = false
dragStartPos = null
dragStartMouse = null
otherSelectedNodesStartPositions = null
// Release pointer
const target = event.target as HTMLElement
target.releasePointerCapture(event.pointerId)
if (!(event.target instanceof HTMLElement)) return
event.target.releasePointerCapture(event.pointerId)
}
/**
@@ -177,6 +183,7 @@ export function useNodeLayout(nodeIdMaybe: MaybeRefOrGetter<string>) {
bounds,
isVisible,
zIndex,
isDragging,
// Mutations
moveTo,
@@ -196,7 +203,7 @@ export function useNodeLayout(nodeIdMaybe: MaybeRefOrGetter<string>) {
width: `${size.value.width}px`,
height: `${size.value.height}px`,
zIndex: zIndex.value,
cursor: isDragging ? 'grabbing' : 'grab'
cursor: isDragging.value ? 'grabbing' : 'grab'
})
)
}