Skip to content

Commit

Permalink
feat(editor): Update connection line to reuse getCustomPath in new …
Browse files Browse the repository at this point in the history
…canvas (no-changelog) (#10175)
  • Loading branch information
alexgrozav authored and cstuncsik committed Jul 31, 2024
1 parent 0753aea commit eb0f18f
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 3 deletions.
4 changes: 4 additions & 0 deletions packages/editor-ui/src/components/canvas/Canvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,10 @@ watch(() => props.readOnly, setReadonly, {
/>
</template>

<template #connection-line="connectionLineProps">
<CanvasConnectionLine v-bind="connectionLineProps" />
</template>

<Background data-test-id="canvas-background" pattern-color="#aaa" :gap="GRID_SIZE" />

<MiniMap data-test-id="canvas-minimap" pannable />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import CanvasConnectionLine from './CanvasConnectionLine.vue';
import { createComponentRenderer } from '@/__tests__/render';
import { createTestingPinia } from '@pinia/testing';
import { setActivePinia } from 'pinia';
import type { ConnectionLineProps } from '@vue-flow/core';
import { Position } from '@vue-flow/core';

const DEFAULT_PROPS = {
sourceX: 0,
sourceY: 0,
sourcePosition: Position.Top,
targetX: 100,
targetY: 100,
targetPosition: Position.Bottom,
} satisfies Partial<ConnectionLineProps>;
const renderComponent = createComponentRenderer(CanvasConnectionLine, {
props: DEFAULT_PROPS,
});

beforeEach(() => {
const pinia = createTestingPinia();
setActivePinia(pinia);
});

describe('CanvasConnectionLine', () => {
it('should render a correct bezier path', () => {
const { container } = renderComponent({
props: DEFAULT_PROPS,
});

const edge = container.querySelector('.vue-flow__edge-path');

expect(edge).toHaveAttribute('d', 'M0,0 C0,-62.5 100,162.5 100,100');
});

it('should render a correct smooth step path when the connection is backwards', () => {
const { container } = renderComponent({
props: {
...DEFAULT_PROPS,
sourceX: 0,
sourceY: 0,
sourcePosition: Position.Right,
targetX: -100,
targetY: -100,
targetPosition: Position.Left,
},
});

const edge = container.querySelector('.vue-flow__edge-path');

expect(edge).toHaveAttribute(
'd',
'M0 0L 32,0Q 40,0 40,8L 40,132Q 40,140 32,140L1 140L0 140M0 140L-40 140L -132,140Q -140,140 -140,132L -140,-92Q -140,-100 -132,-100L-100 -100',
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts" setup>
/* eslint-disable vue/no-multiple-template-root */
import type { ConnectionLineProps } from '@vue-flow/core';
import { BaseEdge } from '@vue-flow/core';
import { computed, useCssModule } from 'vue';
import { getCustomPath } from './utils/edgePath';
const props = defineProps<ConnectionLineProps>();
const $style = useCssModule();
const edgeStyle = computed(() => ({
strokeWidth: 2,
}));
const path = computed(() => getCustomPath(props));
</script>

<template>
<BaseEdge :class="$style.edge" :style="edgeStyle" :path="path[0]" :marker-end="markerEnd" />
</template>

<style lang="scss" module>
.edge {
transition: stroke 0.3s ease;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { getBezierPath, getSmoothStepPath, Position, type EdgeProps } from '@vue-flow/core';
import type { EdgeProps } from '@vue-flow/core';
import { getBezierPath, getSmoothStepPath, Position } from '@vue-flow/core';

const EDGE_PADDING_Y = 140;
const EDGE_PADDING_Y_TOP = 80;
const EDGE_BORDER_RADIUS = 8;
const EDGE_OFFSET = 40;
const HANDLE_SIZE = 16;

export function getCustomPath(props: EdgeProps) {
export function getCustomPath(
props: Pick<
EdgeProps,
'sourceX' | 'sourceY' | 'sourcePosition' | 'targetX' | 'targetY' | 'targetPosition'
>,
) {
const { targetX, targetY, sourceX, sourceY, sourcePosition, targetPosition } = props;
const xDiff = targetX - sourceX;
const yDiff = targetY - sourceY;

// Connection is backwards and the source is on the right side
// -> We need to avoid overlapping the source node
if (xDiff < 0 && sourcePosition === Position.Right) {
if (xDiff < -HANDLE_SIZE && sourcePosition === Position.Right) {
const direction = yDiff < -EDGE_PADDING_Y || yDiff > 0 ? 'up' : 'down';
const firstSegmentTargetX = sourceX;
const firstSegmentTargetY =
Expand Down Expand Up @@ -41,5 +48,6 @@ export function getCustomPath(props: EdgeProps) {
path[0] = firstSegmentPath + path[0];
return path;
}

return getBezierPath(props);
}

0 comments on commit eb0f18f

Please sign in to comment.