Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): calculate handle positions correctly #1625

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/clever-eyes-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@vue-flow/core": patch
---

Prevent page scroll when using arrow keys to move nodes.
17 changes: 5 additions & 12 deletions packages/core/src/components/ConnectionLine/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import { computed, defineComponent, h, inject } from 'vue'
import type { HandleElement } from '../../types'
import { ConnectionLineType, ConnectionMode, Position } from '../../types'
import { getHandlePosition, getMarkerId } from '../../utils'
import { getHandlePosition, getMarkerId, oppositePosition } from '../../utils'
import { useVueFlow } from '../../composables'
import { Slots } from '../../context'
import { getBezierPath, getSimpleBezierPath, getSmoothStepPath } from '../Edges/utils'

const oppositePosition = {
[Position.Left]: Position.Right,
[Position.Right]: Position.Left,
[Position.Top]: Position.Bottom,
[Position.Bottom]: Position.Top,
}

const ConnectionLine = defineComponent({
name: 'ConnectionLine',
compatConfig: { MODE: 3 },
Expand Down Expand Up @@ -57,7 +50,7 @@ const ConnectionLine = defineComponent({
return null
}

const startHandleId = connectionStartHandle.value.handleId
const startHandleId = connectionStartHandle.value.id

const handleType = connectionStartHandle.value.type

Expand All @@ -78,18 +71,18 @@ const ConnectionLine = defineComponent({
const { x: fromX, y: fromY } = getHandlePosition(fromNode.value, fromHandle, fromPosition)

let toHandle: HandleElement | null = null
if (toNode.value && connectionEndHandle.value?.handleId) {
if (toNode.value) {
// if connection mode is strict, we only look for handles of the opposite type
if (connectionMode.value === ConnectionMode.Strict) {
toHandle =
toNode.value.handleBounds[handleType === 'source' ? 'target' : 'source']?.find(
(d) => d.id === connectionEndHandle.value?.handleId,
(d) => d.id === connectionEndHandle.value?.id,
) || null
} else {
// if connection mode is loose, look for the handle in both source and target bounds
toHandle =
[...(toNode.value.handleBounds.source || []), ...(toNode.value.handleBounds.target || [])]?.find(
(d) => d.id === connectionEndHandle.value?.handleId,
(d) => d.id === connectionEndHandle.value?.id,
) || null
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/components/Edges/EdgeWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
ErrorCode,
VueFlowError,
elementSelectionKeys,
getHandle,
getEdgeHandle,
getHandlePosition,
getMarkerId,
} from '../../utils'
Expand Down Expand Up @@ -150,7 +150,7 @@ const EdgeWrapper = defineComponent({
sourceNodeHandles = [...(sourceNode.handleBounds.source || []), ...(sourceNode.handleBounds.target || [])]
}

const sourceHandle = getHandle(sourceNodeHandles, edge.value.sourceHandle)
const sourceHandle = getEdgeHandle(sourceNodeHandles, edge.value.sourceHandle)

let targetNodeHandles
if (connectionMode.value === ConnectionMode.Strict) {
Expand All @@ -159,7 +159,7 @@ const EdgeWrapper = defineComponent({
targetNodeHandles = [...(targetNode.handleBounds.target || []), ...(targetNode.handleBounds.source || [])]
}

const targetHandle = getHandle(targetNodeHandles, edge.value.targetHandle)
const targetHandle = getEdgeHandle(targetNodeHandles, edge.value.targetHandle)

const sourcePosition = sourceHandle?.position || Position.Bottom

Expand Down
11 changes: 7 additions & 4 deletions packages/core/src/components/Handle/Handle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const type = toRef(() => props.type ?? 'source')
const isValidConnection = toRef(() => props.isValidConnection ?? null)

const {
id: flowId,
connectionStartHandle,
connectionClickStartHandle,
connectionEndHandle,
Expand All @@ -39,17 +40,17 @@ const isConnectableEnd = toRef(() => (typeof connectableEnd !== 'undefined' ? co
const isConnecting = toRef(
() =>
(connectionStartHandle.value?.nodeId === nodeId &&
connectionStartHandle.value?.handleId === handleId &&
connectionStartHandle.value?.id === handleId &&
connectionStartHandle.value?.type === type.value) ||
(connectionEndHandle.value?.nodeId === nodeId &&
connectionEndHandle.value?.handleId === handleId &&
connectionEndHandle.value?.id === handleId &&
connectionEndHandle.value?.type === type.value),
)

const isClickConnecting = toRef(
() =>
connectionClickStartHandle.value?.nodeId === nodeId &&
connectionClickStartHandle.value?.handleId === handleId &&
connectionClickStartHandle.value?.id === handleId &&
connectionClickStartHandle.value?.type === type.value,
)

Expand Down Expand Up @@ -127,6 +128,8 @@ onMounted(() => {
position,
x: (handleBounds.left - nodeBounds.left) / zoom,
y: (handleBounds.top - nodeBounds.top) / zoom,
type: type.value,
nodeId,
...getDimensions(handle.value),
}

Expand Down Expand Up @@ -177,7 +180,7 @@ export default {
<template>
<div
ref="handle"
:data-id="`${nodeId}-${handleId}-${type}`"
:data-id="`${flowId}-${nodeId}-${handleId}-${type}`"
:data-handleid="handleId"
:data-nodeid="nodeId"
:data-handlepos="position"
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/components/Nodes/NodeWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,9 @@ const NodeWrapper = defineComponent({
nodeElement.value!,
)
} else if (isDraggable.value && node.selected && arrowKeyDiffs[event.key]) {
// prevent page scrolling
event.preventDefault()

ariaLiveMessage.value = `Moved selected node ${event.key.replace('Arrow', '').toLowerCase()}. New position, x: ${~~node
.position.x}, y: ${~~node.position.y}`

Expand Down
Loading
Loading