mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(editor): Fix showing and hiding canvas edge toolbar when hovering (#13009)
This commit is contained in:
parent
37d152c148
commit
ac7bc4f191
|
@ -45,8 +45,8 @@
|
||||||
"@typescript/vfs": "^1.6.0",
|
"@typescript/vfs": "^1.6.0",
|
||||||
"@vue-flow/background": "^1.3.2",
|
"@vue-flow/background": "^1.3.2",
|
||||||
"@vue-flow/controls": "^1.1.2",
|
"@vue-flow/controls": "^1.1.2",
|
||||||
"@vue-flow/core": "^1.41.6",
|
"@vue-flow/core": "^1.42.1",
|
||||||
"@vue-flow/minimap": "^1.5.0",
|
"@vue-flow/minimap": "^1.5.2",
|
||||||
"@vue-flow/node-resizer": "^1.4.0",
|
"@vue-flow/node-resizer": "^1.4.0",
|
||||||
"@vueuse/components": "^10.11.0",
|
"@vueuse/components": "^10.11.0",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
|
|
|
@ -71,6 +71,30 @@ describe('CanvasEdge', () => {
|
||||||
expect(() => getByTestId('delete-connection-button')).toThrow();
|
expect(() => getByTestId('delete-connection-button')).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should hide toolbar after delay', async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
|
||||||
|
const user = userEvent.setup({
|
||||||
|
advanceTimers: vi.advanceTimersByTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { rerender, getByTestId, queryByTestId } = renderComponent({
|
||||||
|
props: { hovered: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.hover(getByTestId('edge-label'));
|
||||||
|
expect(queryByTestId('canvas-edge-toolbar')).toBeInTheDocument();
|
||||||
|
|
||||||
|
await rerender({ hovered: false });
|
||||||
|
|
||||||
|
await user.unhover(getByTestId('edge-label'));
|
||||||
|
expect(getByTestId('canvas-edge-toolbar')).toBeInTheDocument();
|
||||||
|
|
||||||
|
await vi.advanceTimersByTimeAsync(300);
|
||||||
|
|
||||||
|
expect(queryByTestId('canvas-edge-toolbar')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it('should compute edgeStyle correctly', () => {
|
it('should compute edgeStyle correctly', () => {
|
||||||
const { container } = renderComponent();
|
const { container } = renderComponent();
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { isValidNodeConnectionType } from '@/utils/typeGuards';
|
||||||
import type { Connection, EdgeProps } from '@vue-flow/core';
|
import type { Connection, EdgeProps } from '@vue-flow/core';
|
||||||
import { BaseEdge, EdgeLabelRenderer } from '@vue-flow/core';
|
import { BaseEdge, EdgeLabelRenderer } from '@vue-flow/core';
|
||||||
import { NodeConnectionType } from 'n8n-workflow';
|
import { NodeConnectionType } from 'n8n-workflow';
|
||||||
import { computed, toRef, useCssModule } from 'vue';
|
import { computed, ref, toRef, useCssModule, watch } from 'vue';
|
||||||
import CanvasEdgeToolbar from './CanvasEdgeToolbar.vue';
|
import CanvasEdgeToolbar from './CanvasEdgeToolbar.vue';
|
||||||
import { getEdgeRenderData } from './utils';
|
import { getEdgeRenderData } from './utils';
|
||||||
|
|
||||||
|
@ -33,7 +33,26 @@ const connectionType = computed(() =>
|
||||||
: NodeConnectionType.Main,
|
: NodeConnectionType.Main,
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderToolbar = computed(() => props.hovered && !props.readOnly);
|
const delayedHovered = ref(props.hovered);
|
||||||
|
const delayedHoveredSetTimeoutRef = ref<NodeJS.Timeout | null>(null);
|
||||||
|
const delayedHoveredTimeout = 300;
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.hovered,
|
||||||
|
(isHovered) => {
|
||||||
|
if (isHovered) {
|
||||||
|
if (delayedHoveredSetTimeoutRef.value) clearTimeout(delayedHoveredSetTimeoutRef.value);
|
||||||
|
delayedHovered.value = true;
|
||||||
|
} else {
|
||||||
|
delayedHoveredSetTimeoutRef.value = setTimeout(() => {
|
||||||
|
delayedHovered.value = false;
|
||||||
|
}, delayedHoveredTimeout);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderToolbar = computed(() => (props.selected || delayedHovered.value) && !props.readOnly);
|
||||||
|
|
||||||
const isMainConnection = computed(() => data.value.source.type === NodeConnectionType.Main);
|
const isMainConnection = computed(() => data.value.source.type === NodeConnectionType.Main);
|
||||||
|
|
||||||
|
|
|
@ -1443,19 +1443,19 @@ importers:
|
||||||
version: 1.6.0(typescript@5.7.2)
|
version: 1.6.0(typescript@5.7.2)
|
||||||
'@vue-flow/background':
|
'@vue-flow/background':
|
||||||
specifier: ^1.3.2
|
specifier: ^1.3.2
|
||||||
version: 1.3.2(@vue-flow/core@1.41.6(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
version: 1.3.2(@vue-flow/core@1.42.1(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
||||||
'@vue-flow/controls':
|
'@vue-flow/controls':
|
||||||
specifier: ^1.1.2
|
specifier: ^1.1.2
|
||||||
version: 1.1.2(@vue-flow/core@1.41.6(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
version: 1.1.2(@vue-flow/core@1.42.1(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
||||||
'@vue-flow/core':
|
'@vue-flow/core':
|
||||||
specifier: ^1.41.6
|
specifier: ^1.42.1
|
||||||
version: 1.41.6(vue@3.5.13(typescript@5.7.2))
|
version: 1.42.1(vue@3.5.13(typescript@5.7.2))
|
||||||
'@vue-flow/minimap':
|
'@vue-flow/minimap':
|
||||||
specifier: ^1.5.0
|
specifier: ^1.5.2
|
||||||
version: 1.5.0(@vue-flow/core@1.41.6(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
version: 1.5.2(@vue-flow/core@1.42.1(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
||||||
'@vue-flow/node-resizer':
|
'@vue-flow/node-resizer':
|
||||||
specifier: ^1.4.0
|
specifier: ^1.4.0
|
||||||
version: 1.4.0(@vue-flow/core@1.41.6(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
version: 1.4.0(@vue-flow/core@1.42.1(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
||||||
'@vueuse/components':
|
'@vueuse/components':
|
||||||
specifier: ^10.11.0
|
specifier: ^10.11.0
|
||||||
version: 10.11.0(vue@3.5.13(typescript@5.7.2))
|
version: 10.11.0(vue@3.5.13(typescript@5.7.2))
|
||||||
|
@ -6288,13 +6288,13 @@ packages:
|
||||||
'@vue-flow/core': ^1.23.0
|
'@vue-flow/core': ^1.23.0
|
||||||
vue: ^3.3.0
|
vue: ^3.3.0
|
||||||
|
|
||||||
'@vue-flow/core@1.41.6':
|
'@vue-flow/core@1.42.1':
|
||||||
resolution: {integrity: sha512-8zxcGRqiudra0obDMLTg9L89WxdlV0QrDOdyPYOKWDcD/UK5aT0MIL3Br9TF9AJmHW2z8QZq4cmmgroREL0jgQ==}
|
resolution: {integrity: sha512-QzzTxMAXfOeETKc+N3XMp5XpiPxKBHK5kq98avgTsE6MXyeU2E8EkANwwgSB/hvJ/k36RjU0Y7BOwCHiqiI1tw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vue: ^3.3.0
|
vue: ^3.3.0
|
||||||
|
|
||||||
'@vue-flow/minimap@1.5.0':
|
'@vue-flow/minimap@1.5.2':
|
||||||
resolution: {integrity: sha512-JhxXDF+8uTc7sgkZHDIvFpHqSl4wsK9xp8Kz5OHwNcXlgGcwqj4yad6jcc1B6bGxm+huESpNmoPotQbpMn6rVw==}
|
resolution: {integrity: sha512-XNSpWwwXfCWqJilc2eCW+3ry3r9vhF8HmUw5wrAsUTHiss4R9k5uZLABo7c3T3VdcVRJ8pTfUJ9vjpzb8H+FKg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@vue-flow/core': ^1.23.0
|
'@vue-flow/core': ^1.23.0
|
||||||
vue: ^3.3.0
|
vue: ^3.3.0
|
||||||
|
@ -19361,17 +19361,17 @@ snapshots:
|
||||||
path-browserify: 1.0.1
|
path-browserify: 1.0.1
|
||||||
vscode-uri: 3.0.8
|
vscode-uri: 3.0.8
|
||||||
|
|
||||||
'@vue-flow/background@1.3.2(@vue-flow/core@1.41.6(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
'@vue-flow/background@1.3.2(@vue-flow/core@1.42.1(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue-flow/core': 1.41.6(vue@3.5.13(typescript@5.7.2))
|
'@vue-flow/core': 1.42.1(vue@3.5.13(typescript@5.7.2))
|
||||||
vue: 3.5.13(typescript@5.7.2)
|
vue: 3.5.13(typescript@5.7.2)
|
||||||
|
|
||||||
'@vue-flow/controls@1.1.2(@vue-flow/core@1.41.6(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
'@vue-flow/controls@1.1.2(@vue-flow/core@1.42.1(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue-flow/core': 1.41.6(vue@3.5.13(typescript@5.7.2))
|
'@vue-flow/core': 1.42.1(vue@3.5.13(typescript@5.7.2))
|
||||||
vue: 3.5.13(typescript@5.7.2)
|
vue: 3.5.13(typescript@5.7.2)
|
||||||
|
|
||||||
'@vue-flow/core@1.41.6(vue@3.5.13(typescript@5.7.2))':
|
'@vue-flow/core@1.42.1(vue@3.5.13(typescript@5.7.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vueuse/core': 10.11.0(vue@3.5.13(typescript@5.7.2))
|
'@vueuse/core': 10.11.0(vue@3.5.13(typescript@5.7.2))
|
||||||
d3-drag: 3.0.0
|
d3-drag: 3.0.0
|
||||||
|
@ -19381,16 +19381,16 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
|
|
||||||
'@vue-flow/minimap@1.5.0(@vue-flow/core@1.41.6(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
'@vue-flow/minimap@1.5.2(@vue-flow/core@1.42.1(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue-flow/core': 1.41.6(vue@3.5.13(typescript@5.7.2))
|
'@vue-flow/core': 1.42.1(vue@3.5.13(typescript@5.7.2))
|
||||||
d3-selection: 3.0.0
|
d3-selection: 3.0.0
|
||||||
d3-zoom: 3.0.0
|
d3-zoom: 3.0.0
|
||||||
vue: 3.5.13(typescript@5.7.2)
|
vue: 3.5.13(typescript@5.7.2)
|
||||||
|
|
||||||
'@vue-flow/node-resizer@1.4.0(@vue-flow/core@1.41.6(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
'@vue-flow/node-resizer@1.4.0(@vue-flow/core@1.42.1(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue-flow/core': 1.41.6(vue@3.5.13(typescript@5.7.2))
|
'@vue-flow/core': 1.42.1(vue@3.5.13(typescript@5.7.2))
|
||||||
d3-drag: 3.0.0
|
d3-drag: 3.0.0
|
||||||
d3-selection: 3.0.0
|
d3-selection: 3.0.0
|
||||||
vue: 3.5.13(typescript@5.7.2)
|
vue: 3.5.13(typescript@5.7.2)
|
||||||
|
|
Loading…
Reference in a new issue