Skip to content

Commit

Permalink
fix(core): check if dragEnd event is actually a UseDrag or MouseTouch…
Browse files Browse the repository at this point in the history
… event

Signed-off-by: braks <[email protected]>
  • Loading branch information
bcakmakoglu committed Nov 7, 2024
1 parent f2d8b2e commit b2c7a9b
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 35 deletions.
22 changes: 12 additions & 10 deletions packages/core/src/components/Nodes/NodeWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ import {
elementSelectionKeys,
getXYZPos,
handleNodeClick,
snapPosition,
} from '../../utils'
import { NodeId, NodeRef, Slots } from '../../context'
import { isInputDOMNode, useDrag, useNode, useNodeHooks, useUpdateNodePositions, useVueFlow } from '../../composables'
import type { NodeComponent } from '../../types'
import type { MouseTouchEvent, NodeComponent } from '../../types'

interface Props {
id: string
Expand Down Expand Up @@ -321,14 +322,15 @@ const NodeWrapper = defineComponent({
}
/** this re-calculates the current position, necessary for clamping by a node's extent */
function clampPosition() {
const nextPos = node.computedPosition

if (snapToGrid.value) {
nextPos.x = snapGrid.value[0] * Math.round(nextPos.x / snapGrid.value[0])
nextPos.y = snapGrid.value[1] * Math.round(nextPos.y / snapGrid.value[1])
}

const { computedPosition, position } = calcNextPosition(node, nextPos, emits.error, nodeExtent.value, parentNode.value)
const nextPosition = node.computedPosition

const { computedPosition, position } = calcNextPosition(
node,
snapToGrid.value ? snapPosition(nextPosition, snapGrid.value) : nextPosition,
emits.error,
nodeExtent.value,
parentNode.value,
)

// only overwrite positions if there are changes when clamping
if (node.computedPosition.x !== computedPosition.x || node.computedPosition.y !== computedPosition.y) {
Expand Down Expand Up @@ -372,7 +374,7 @@ const NodeWrapper = defineComponent({
return emit.doubleClick({ event, node })
}

function onSelectNode(event: MouseEvent) {
function onSelectNode(event: MouseTouchEvent) {
if (isSelectable.value && (!selectNodesOnDrag.value || !isDraggable.value || nodeDragThreshold.value > 0)) {
handleNodeClick(
node,
Expand Down
27 changes: 13 additions & 14 deletions packages/core/src/composables/useDrag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { drag } from 'd3-drag'
import { select } from 'd3-selection'
import type { MaybeRefOrGetter, Ref } from 'vue'
import { ref, toValue, watch } from 'vue'
import type { NodeDragEvent, NodeDragItem, XYPosition } from '../types'
import type { MouseTouchEvent, NodeDragEvent, NodeDragItem, XYPosition } from '../types'
import {
calcAutoPan,
calcNextPosition,
Expand All @@ -12,6 +12,8 @@ import {
getEventPosition,
handleNodeClick,
hasSelector,
isUseDragEvent,
snapPosition,
} from '../utils'
import { useGetPointerPosition, useVueFlow } from '.'

Expand All @@ -21,7 +23,7 @@ interface UseDragParams {
onStart: (event: NodeDragEvent) => void
onDrag: (event: NodeDragEvent) => void
onStop: (event: NodeDragEvent) => void
onClick?: (event: MouseEvent) => void
onClick?: (event: MouseTouchEvent) => void
el: Ref<Element | null>
disabled?: MaybeRefOrGetter<boolean>
selectable?: MaybeRefOrGetter<boolean>
Expand Down Expand Up @@ -87,14 +89,9 @@ export function useDrag(params: UseDragParams) {
dragItems = dragItems.map((n) => {
const nextPosition = { x: x - n.distance.x, y: y - n.distance.y }

if (snapToGrid.value) {
nextPosition.x = snapGrid.value[0] * Math.round(nextPosition.x / snapGrid.value[0])
nextPosition.y = snapGrid.value[1] * Math.round(nextPosition.y / snapGrid.value[1])
}

const { computedPosition } = calcNextPosition(
n,
nextPosition,
snapToGrid.value ? snapPosition(nextPosition, snapGrid.value) : nextPosition,
emits.error,
nodeExtent.value,
n.parentNode ? findNode(n.parentNode) : undefined,
Expand Down Expand Up @@ -171,7 +168,7 @@ export function useDrag(params: UseDragParams) {
)
}

const pointerPos = getPointerPosition(event)
const pointerPos = getPointerPosition(event.sourceEvent)
lastPos = pointerPos
dragItems = getDragItems(nodes.value, nodesDraggable.value, pointerPos, findNode, id)

Expand All @@ -195,14 +192,14 @@ export function useDrag(params: UseDragParams) {
startDrag(event, nodeEl)
}

lastPos = getPointerPosition(event)
lastPos = getPointerPosition(event.sourceEvent)

containerBounds = vueFlowRef.value?.getBoundingClientRect() || null
mousePosition = getEventPosition(event.sourceEvent, containerBounds!)
}

const eventDrag = (event: UseDragEvent, nodeEl: Element) => {
const pointerPos = getPointerPosition(event)
const pointerPos = getPointerPosition(event.sourceEvent)

if (!autoPanStarted && dragStarted && autoPanOnNodeDrag.value) {
autoPanStarted = true
Expand All @@ -229,16 +226,18 @@ export function useDrag(params: UseDragParams) {
}

const eventEnd = (event: UseDragEvent) => {
if (!dragStarted && !dragging.value && !multiSelectionActive.value) {
const pointerPos = getPointerPosition(event)
if (!isUseDragEvent(event) && !dragStarted && !dragging.value && !multiSelectionActive.value) {
const evt = event as MouseTouchEvent

const pointerPos = getPointerPosition(evt)

const x = pointerPos.xSnapped - (lastPos.x ?? 0)
const y = pointerPos.ySnapped - (lastPos.y ?? 0)
const distance = Math.sqrt(x * x + y * y)

// dispatch a click event if the node was attempted to be dragged but the threshold was not exceeded
if (distance !== 0 && distance <= nodeDragThreshold.value) {
onClick?.(event.sourceEvent)
onClick?.(evt)
}

return
Expand Down
18 changes: 7 additions & 11 deletions packages/core/src/composables/useGetPointerPosition.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { UseDragEvent } from './useDrag'
import { getEventPosition, pointToRendererPoint, snapPosition } from '../utils'
import { useVueFlow } from './useVueFlow'

/**
Expand All @@ -10,19 +10,15 @@ export function useGetPointerPosition() {
const { viewport, snapGrid, snapToGrid } = useVueFlow()

// returns the pointer position projected to the VF coordinate system
return ({ sourceEvent }: UseDragEvent) => {
const x = sourceEvent.touches ? sourceEvent.touches[0].clientX : sourceEvent.clientX
const y = sourceEvent.touches ? sourceEvent.touches[0].clientY : sourceEvent.clientY

const pointerPos = {
x: (x - viewport.value.x) / viewport.value.zoom,
y: (y - viewport.value.y) / viewport.value.zoom,
}
return (event: MouseEvent | TouchEvent) => {
const { x, y } = getEventPosition(event)
const pointerPos = pointToRendererPoint({ x, y }, viewport.value)
const { x: xSnapped, y: ySnapped } = snapToGrid.value ? snapPosition(pointerPos, snapGrid.value) : pointerPos

// we need the snapped position in order to be able to skip unnecessary drag events
return {
xSnapped: snapToGrid.value ? snapGrid.value[0] * Math.round(pointerPos.x / snapGrid.value[0]) : pointerPos.x,
ySnapped: snapToGrid.value ? snapGrid.value[1] * Math.round(pointerPos.y / snapGrid.value[1]) : pointerPos.y,
xSnapped,
ySnapped,
...pointerPos,
}
}
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/utils/general.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import type { GraphNode, SnapGrid, XYPosition } from '../types'
import type { UseDragEvent } from '../composables'

export function isMouseEvent(event: MouseEvent | TouchEvent): event is MouseEvent {
return 'clientX' in event
}

export function isUseDragEvent(event: any): event is UseDragEvent {
return 'sourceEvent' in event
}

export function getEventPosition(event: MouseEvent | TouchEvent, bounds?: DOMRect) {
const isMouse = isMouseEvent(event)

Expand Down

0 comments on commit b2c7a9b

Please sign in to comment.