mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-26 05:04:05 -08:00
fix(editor): Support middle click to scroll when using a mouse on new canvas (#11384)
This commit is contained in:
parent
74d870530b
commit
46f3b4a258
|
@ -220,4 +220,20 @@ describe('Canvas', () => {
|
||||||
expect(container.querySelector('#diagonalHatch')).toBeInTheDocument();
|
expect(container.querySelector('#diagonalHatch')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('pane', () => {
|
||||||
|
describe('onPaneMouseDown', () => {
|
||||||
|
it('should enable panning when middle mouse button is pressed', async () => {
|
||||||
|
const { getByTestId } = renderComponent();
|
||||||
|
const canvas = getByTestId('canvas');
|
||||||
|
const pane = canvas.querySelector('.vue-flow__pane');
|
||||||
|
|
||||||
|
if (!pane) throw new Error('VueFlow pane not in the document');
|
||||||
|
|
||||||
|
await fireEvent.mouseDown(canvas, { button: 1, view: window });
|
||||||
|
|
||||||
|
expect(canvas).toHaveClass('draggable');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,6 +43,7 @@ import { onKeyDown, onKeyUp, useDebounceFn } from '@vueuse/core';
|
||||||
import CanvasArrowHeadMarker from './elements/edges/CanvasArrowHeadMarker.vue';
|
import CanvasArrowHeadMarker from './elements/edges/CanvasArrowHeadMarker.vue';
|
||||||
import { CanvasNodeRenderType } from '@/types';
|
import { CanvasNodeRenderType } from '@/types';
|
||||||
import CanvasBackgroundStripedPattern from './elements/CanvasBackgroundStripedPattern.vue';
|
import CanvasBackgroundStripedPattern from './elements/CanvasBackgroundStripedPattern.vue';
|
||||||
|
import { isMiddleMouseButton } from '@/utils/eventUtils';
|
||||||
|
|
||||||
const $style = useCssModule();
|
const $style = useCssModule();
|
||||||
|
|
||||||
|
@ -107,6 +108,7 @@ const props = withDefaults(
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
vueFlowRef,
|
||||||
getSelectedNodes: selectedNodes,
|
getSelectedNodes: selectedNodes,
|
||||||
addSelectedNodes,
|
addSelectedNodes,
|
||||||
removeSelectedNodes,
|
removeSelectedNodes,
|
||||||
|
@ -143,18 +145,16 @@ const disableKeyBindings = computed(() => !props.keyBindings);
|
||||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values#whitespace_keys
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values#whitespace_keys
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const isPanningEnabled = ref(false);
|
|
||||||
const panningKeyCode = ' ';
|
const panningKeyCode = ' ';
|
||||||
|
const isPanningEnabled = ref(false);
|
||||||
const selectionKeyCode = ref<true | null>(true);
|
const selectionKeyCode = ref<true | null>(true);
|
||||||
|
|
||||||
onKeyDown(panningKeyCode, () => {
|
onKeyDown(panningKeyCode, () => {
|
||||||
isPanningEnabled.value = true;
|
setPanningEnabled(true);
|
||||||
selectionKeyCode.value = null;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onKeyUp(panningKeyCode, () => {
|
onKeyUp(panningKeyCode, () => {
|
||||||
isPanningEnabled.value = false;
|
setPanningEnabled(false);
|
||||||
selectionKeyCode.value = true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const keyMap = computed(() => ({
|
const keyMap = computed(() => ({
|
||||||
|
@ -186,6 +186,16 @@ const keyMap = computed(() => ({
|
||||||
|
|
||||||
useKeybindings(keyMap, { disabled: disableKeyBindings });
|
useKeybindings(keyMap, { disabled: disableKeyBindings });
|
||||||
|
|
||||||
|
function setPanningEnabled(value: boolean) {
|
||||||
|
if (value) {
|
||||||
|
isPanningEnabled.value = true;
|
||||||
|
selectionKeyCode.value = null;
|
||||||
|
} else {
|
||||||
|
isPanningEnabled.value = false;
|
||||||
|
selectionKeyCode.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the window is focused, the selection key code is lost.
|
* When the window is focused, the selection key code is lost.
|
||||||
* We trigger a value refresh to ensure that the selection key code is set correctly again.
|
* We trigger a value refresh to ensure that the selection key code is set correctly again.
|
||||||
|
@ -384,12 +394,28 @@ function setReadonly(value: boolean) {
|
||||||
elementsSelectable.value = true;
|
elementsSelectable.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onPaneMouseDown(event: MouseEvent) {
|
||||||
|
if (isMiddleMouseButton(event)) {
|
||||||
|
setPanningEnabled(true);
|
||||||
|
|
||||||
|
// Re-emit the event to start panning after setting the panning state to true
|
||||||
|
// This workaround is necessary because the Vue Flow library does not provide a way to
|
||||||
|
// start panning programmatically
|
||||||
|
void nextTick(() =>
|
||||||
|
vueFlowRef.value
|
||||||
|
?.querySelector('.vue-flow__pane')
|
||||||
|
?.dispatchEvent(new MouseEvent('mousedown', event)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onPaneMoveStart() {
|
function onPaneMoveStart() {
|
||||||
isPaneMoving.value = true;
|
isPaneMoving.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPaneMoveEnd() {
|
function onPaneMoveEnd() {
|
||||||
isPaneMoving.value = false;
|
isPaneMoving.value = false;
|
||||||
|
setPanningEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -559,6 +585,7 @@ provide(CanvasKey, {
|
||||||
@nodes-change="onNodesChange"
|
@nodes-change="onNodesChange"
|
||||||
@move-start="onPaneMoveStart"
|
@move-start="onPaneMoveStart"
|
||||||
@move-end="onPaneMoveEnd"
|
@move-end="onPaneMoveEnd"
|
||||||
|
@mousedown="onPaneMouseDown"
|
||||||
>
|
>
|
||||||
<template #node-canvas-node="canvasNodeProps">
|
<template #node-canvas-node="canvasNodeProps">
|
||||||
<Node
|
<Node
|
||||||
|
@ -647,6 +674,10 @@ provide(CanvasKey, {
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.vue-flow__pane) {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
:global(.vue-flow__pane.dragging) {
|
:global(.vue-flow__pane.dragging) {
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,17 +58,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Pane
|
|
||||||
*/
|
|
||||||
|
|
||||||
.vue-flow__pane {
|
|
||||||
&,
|
|
||||||
&.draggable {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nodes
|
* Nodes
|
||||||
*/
|
*/
|
||||||
|
|
3
packages/editor-ui/src/utils/eventUtils.ts
Normal file
3
packages/editor-ui/src/utils/eventUtils.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export function isMiddleMouseButton(event: MouseEvent) {
|
||||||
|
return event.which === 2 || event.button === 1;
|
||||||
|
}
|
Loading…
Reference in a new issue