From b781095be14d8dc973924d0cc55db49b0944fe4e Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Thu, 25 Jul 2024 07:54:58 +0300 Subject: [PATCH] feat(editor): Update connection line to reuse `getCustomPath` in new canvas (no-changelog) (#10175) --- .../src/components/canvas/Canvas.vue | 4 ++ .../edges/CanvasConnectionLine.spec.ts | 56 +++++++++++++++++++ .../elements/edges/CanvasConnectionLine.vue | 27 +++++++++ .../canvas/elements/edges/utils/edgePath.ts | 14 ++++- 4 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts create mode 100644 packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.vue diff --git a/packages/editor-ui/src/components/canvas/Canvas.vue b/packages/editor-ui/src/components/canvas/Canvas.vue index f4c734cd98..c5995c5cd6 100644 --- a/packages/editor-ui/src/components/canvas/Canvas.vue +++ b/packages/editor-ui/src/components/canvas/Canvas.vue @@ -401,6 +401,10 @@ watch(() => props.readOnly, setReadonly, { /> + + diff --git a/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts b/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts new file mode 100644 index 0000000000..876cde7ca6 --- /dev/null +++ b/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts @@ -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; +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', + ); + }); +}); diff --git a/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.vue b/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.vue new file mode 100644 index 0000000000..86b1a5971d --- /dev/null +++ b/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/packages/editor-ui/src/components/canvas/elements/edges/utils/edgePath.ts b/packages/editor-ui/src/components/canvas/elements/edges/utils/edgePath.ts index 0a98519bbb..348a0283b8 100644 --- a/packages/editor-ui/src/components/canvas/elements/edges/utils/edgePath.ts +++ b/packages/editor-ui/src/components/canvas/elements/edges/utils/edgePath.ts @@ -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 = @@ -41,5 +48,6 @@ export function getCustomPath(props: EdgeProps) { path[0] = firstSegmentPath + path[0]; return path; } + return getBezierPath(props); }