diff --git a/packages/editor-ui/src/components/canvas/Canvas.vue b/packages/editor-ui/src/components/canvas/Canvas.vue index 555303ce6a..96f3c8d640 100644 --- a/packages/editor-ui/src/components/canvas/Canvas.vue +++ b/packages/editor-ui/src/components/canvas/Canvas.vue @@ -8,6 +8,8 @@ import { MiniMap } from '@vue-flow/minimap'; import Node from './elements/nodes/CanvasNode.vue'; import Edge from './elements/edges/CanvasEdge.vue'; import { onMounted, onUnmounted, ref, useCssModule } from 'vue'; +import type { EventBus } from 'n8n-design-system'; +import { createEventBus } from 'n8n-design-system'; const $style = useCssModule(); @@ -34,28 +36,24 @@ const props = withDefaults( nodes: CanvasNode[]; connections: CanvasConnection[]; controlsPosition?: PanelPosition; + eventBus?: EventBus; }>(), { id: 'canvas', nodes: () => [], connections: () => [], controlsPosition: PanelPosition.BottomLeft, + eventBus: () => createEventBus(), }, ); -const { getSelectedEdges, getSelectedNodes, viewportRef, project } = useVueFlow({ +const { getSelectedEdges, getSelectedNodes, viewportRef, fitView, project } = useVueFlow({ id: props.id, }); -const hoveredEdges = ref>({}); - -onMounted(() => { - document.addEventListener('keydown', onKeyDown); -}); - -onUnmounted(() => { - document.removeEventListener('keydown', onKeyDown); -}); +/** + * Nodes + */ function onNodeDragStop(e: NodeDragEvent) { e.nodes.forEach((node) => { @@ -128,16 +126,11 @@ function onClickConnectionAdd(connection: Connection) { emit('click:connection:add', connection); } -function onRunNode(id: string) { - emit('run:node', id); -} +/** + * Connection hover + */ -function onKeyDown(e: KeyboardEvent) { - if (e.key === 'Delete') { - getSelectedEdges.value.forEach(onDeleteConnection); - getSelectedNodes.value.forEach(({ id }) => onDeleteNode(id)); - } -} +const hoveredEdges = ref>({}); function onMouseEnterEdge(event: EdgeMouseEvent) { hoveredEdges.value[event.edge.id] = true; @@ -147,6 +140,29 @@ function onMouseLeaveEdge(event: EdgeMouseEvent) { hoveredEdges.value[event.edge.id] = false; } +/** + * Executions + */ + +function onRunNode(id: string) { + emit('run:node', id); +} + +/** + * Keyboard events + */ + +function onKeyDown(e: KeyboardEvent) { + if (e.key === 'Delete') { + getSelectedEdges.value.forEach(onDeleteConnection); + getSelectedNodes.value.forEach(({ id }) => onDeleteNode(id)); + } +} + +/** + * View + */ + function onClickPane(event: MouseEvent) { const bounds = viewportRef.value?.getBoundingClientRect() ?? { left: 0, top: 0 }; const position = project({ @@ -156,6 +172,24 @@ function onClickPane(event: MouseEvent) { emit('click:pane', position); } + +async function onFitView() { + await fitView(); +} + +/** + * Lifecycle + */ + +onMounted(() => { + document.addEventListener('keydown', onKeyDown); + props.eventBus.on('fitView', onFitView); +}); + +onUnmounted(() => { + props.eventBus.off('fitView', onFitView); + document.removeEventListener('keydown', onKeyDown); +});