Files
vue-flow/packages/core/src/components/NodesSelection/NodesSelection.vue
T
Braks 600d1a63fd fix(core): prevent scrolling when using arrow keys to move node selection (#1702)
* fix(core): prevent scrolling when using arrow keys to move node selection

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

* chore(changeset): update

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

---------

Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
2024-12-07 16:39:07 +01:00

88 lines
2.1 KiB
Vue

<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'
import { useDrag, useUpdateNodePositions, useVueFlow } from '../../composables'
import { arrowKeyDiffs, getRectOfNodes } from '../../utils'
const { emits, viewport, getSelectedNodes, noPanClassName, disableKeyboardA11y, userSelectionActive } = useVueFlow()
const updatePositions = useUpdateNodePositions()
const el = ref<HTMLDivElement | null>(null)
const dragging = useDrag({
el,
onStart(args) {
emits.selectionDragStart(args)
},
onDrag(args) {
emits.selectionDrag(args)
},
onStop(args) {
emits.selectionDragStop(args)
},
})
onMounted(() => {
if (!disableKeyboardA11y.value) {
el.value?.focus({ preventScroll: true })
}
})
const selectedNodesBBox = computed(() => getRectOfNodes(getSelectedNodes.value))
const innerStyle = computed(() => ({
width: `${selectedNodesBBox.value.width}px`,
height: `${selectedNodesBBox.value.height}px`,
top: `${selectedNodesBBox.value.y}px`,
left: `${selectedNodesBBox.value.x}px`,
}))
function onContextMenu(event: MouseEvent) {
emits.selectionContextMenu({ event, nodes: getSelectedNodes.value })
}
function onKeyDown(event: KeyboardEvent) {
if (disableKeyboardA11y) {
return
}
if (arrowKeyDiffs[event.key]) {
event.preventDefault()
updatePositions(
{
x: arrowKeyDiffs[event.key].x,
y: arrowKeyDiffs[event.key].y,
},
event.shiftKey,
)
}
}
</script>
<script lang="ts">
export default {
name: 'NodesSelection',
compatConfig: { MODE: 3 },
}
</script>
<template>
<div
v-if="!userSelectionActive && selectedNodesBBox.width && selectedNodesBBox.height"
class="vue-flow__nodesselection vue-flow__container"
:class="noPanClassName"
:style="{ transform: `translate(${viewport.x}px,${viewport.y}px) scale(${viewport.zoom})` }"
>
<div
ref="el"
:class="{ dragging }"
class="vue-flow__nodesselection-rect"
:style="innerStyle"
:tabIndex="disableKeyboardA11y ? undefined : -1"
@contextmenu="onContextMenu"
@keydown="onKeyDown"
/>
</div>
</template>