Skip to content

Commit 417b7de

Browse files
authored
feature/MIG-6604 Add markers to the diagram (#24)
1 parent 0d20fab commit 417b7de

File tree

11 files changed

+132
-8
lines changed

11 files changed

+132
-8
lines changed

src/assets/markers/marker-many.svg

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 5 additions & 0 deletions
Loading

src/assets/markers/marker-one.svg

Lines changed: 3 additions & 0 deletions
Loading

src/components/canvas/canvas.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import { Controls } from '@/components/controls/controls';
77
import { Edge, Node as ExternalNode } from '@/types';
88
import { Node } from '@/components/node/node';
99
import { useCanvas } from '@/components/canvas/use-canvas';
10-
import { InternalNode } from '@/types/internal';
10+
import { InternalEdge, InternalNode } from '@/types/internal';
1111
import { FloatingEdge } from '@/components/edge/floating-edge';
1212
import { SelfReferencingEdge } from '@/components/edge/self-referencing-edge';
13+
import { MarkerList } from '@/components/markers/marker-list';
1314

1415
const MAX_ZOOM = 3;
1516
const MIN_ZOOM = 0.1;
@@ -40,7 +41,7 @@ export const Canvas = ({ title, nodes: externalNodes, edges: externalEdges }: Pr
4041
const { initialNodes, initialEdges } = useCanvas(externalNodes, externalEdges);
4142

4243
const [nodes, , onNodesChange] = useNodesState<InternalNode>(initialNodes);
43-
const [edges, , onEdgesChange] = useEdgesState<Edge>(initialEdges);
44+
const [edges, , onEdgesChange] = useEdgesState<InternalEdge>(initialEdges);
4445

4546
return (
4647
<ReactFlowWrapper>
@@ -57,6 +58,7 @@ export const Canvas = ({ title, nodes: externalNodes, edges: externalEdges }: Pr
5758
onNodesChange={onNodesChange}
5859
onEdgesChange={onEdgesChange}
5960
>
61+
<MarkerList />
6062
<Background />
6163
<Controls title={title} />
6264
<MiniMap />

src/components/canvas/use-canvas.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ describe('use-canvas', () => {
5757
expect(result.current.initialEdges).toEqual([
5858
{
5959
id: 'employees-to-orders',
60-
markerEnd: 'one',
61-
markerStart: 'many',
60+
markerEnd: 'end-one',
61+
markerStart: 'start-many',
6262
source: 'employees',
6363
target: 'orders',
6464
type: 'floatingEdge',
@@ -72,8 +72,8 @@ describe('use-canvas', () => {
7272
id: 'employees-to-employees',
7373
source: 'employees',
7474
target: 'employees',
75-
markerEnd: 'one',
76-
markerStart: 'many',
75+
markerEnd: 'end-one',
76+
markerStart: 'start-many',
7777
type: 'selfReferencingEdge',
7878
},
7979
]);

src/components/canvas/use-canvas.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useMemo } from 'react';
22

33
import { Edge, Node as ExternalNode } from '@/types';
4-
import { InternalNode } from '@/types/internal';
4+
import { InternalEdge, InternalNode } from '@/types/internal';
55

66
export const useCanvas = (externalNodes: ExternalNode[], externalEdges: Edge[]) => {
77
const initialNodes: InternalNode[] = useMemo(
@@ -20,10 +20,12 @@ export const useCanvas = (externalNodes: ExternalNode[], externalEdges: Edge[])
2020
[externalNodes],
2121
);
2222

23-
const initialEdges: Edge[] = useMemo(
23+
const initialEdges: InternalEdge[] = useMemo(
2424
() =>
2525
externalEdges.map(edge => ({
2626
...edge,
27+
markerStart: `start-${edge.markerStart}`,
28+
markerEnd: `end-${edge.markerEnd}`,
2729
type: edge.source === edge.target ? 'selfReferencingEdge' : 'floatingEdge',
2830
})),
2931
[externalEdges],
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { render, screen } from '@/mocks/testing-utils';
2+
import { MarkerList } from '@/components/markers/marker-list';
3+
4+
describe('marker-list', () => {
5+
it('Should have markers', () => {
6+
render(<MarkerList />);
7+
expect(screen.getByTestId('start-many')).toBeInTheDocument();
8+
expect(screen.getByTestId('start-one')).toBeInTheDocument();
9+
expect(screen.getByTestId('start-oneOrMany')).toBeInTheDocument();
10+
expect(screen.getByTestId('end-many')).toBeInTheDocument();
11+
expect(screen.getByTestId('end-one')).toBeInTheDocument();
12+
expect(screen.getByTestId('end-oneOrMany')).toBeInTheDocument();
13+
});
14+
});
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { ReactNode } from 'react';
2+
3+
import { Marker } from '@/components/markers/marker';
4+
import MarkerOneOrMany from '@/assets/markers/marker-one-or-many.svg?react';
5+
import MarkerMany from '@/assets/markers/marker-many.svg?react';
6+
import MarkerOne from '@/assets/markers/marker-one.svg?react';
7+
8+
interface MarkerProps extends React.SVGAttributes<SVGMarkerElement> {
9+
component: ReactNode;
10+
}
11+
12+
const markerList: Record<string, MarkerProps> = {
13+
'start-oneOrMany': {
14+
component: <MarkerOneOrMany />,
15+
orient: 'auto-start-reverse',
16+
},
17+
'end-oneOrMany': {
18+
component: <MarkerOneOrMany />,
19+
orient: 'auto',
20+
},
21+
'start-one': {
22+
component: <MarkerOne />,
23+
orient: 'auto-start-reverse',
24+
},
25+
'end-one': {
26+
component: <MarkerOne />,
27+
orient: 'auto',
28+
},
29+
'start-many': {
30+
component: <MarkerMany />,
31+
orient: 'auto-start-reverse',
32+
},
33+
'end-many': {
34+
component: <MarkerMany />,
35+
orient: 'auto',
36+
},
37+
};
38+
39+
export const MarkerList = () => {
40+
return (
41+
<svg>
42+
<defs>
43+
{Object.entries(markerList).map(([id, { component, orient }]) => (
44+
<Marker key={id} data-testid={id} orient={orient} id={id}>
45+
{component}
46+
</Marker>
47+
))}
48+
</defs>
49+
</svg>
50+
);
51+
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { render, screen } from '@/mocks/testing-utils';
2+
import { Marker } from '@/components/markers/marker';
3+
4+
describe('marker', () => {
5+
it('Should render marker', () => {
6+
render(<Marker id={'orders-to-employees'} data-testid={'marker'} orient={'auto'} fill={'#FFF'} />);
7+
const marker = screen.getByTestId('marker');
8+
expect(marker).toBeInTheDocument();
9+
expect(marker).toHaveAttribute('markerHeight', '15');
10+
expect(marker).toHaveAttribute('markerWidth', '15');
11+
expect(marker).toHaveAttribute('refX', '7.5');
12+
expect(marker).toHaveAttribute('refY', '7.5');
13+
expect(marker).toHaveAttribute('orient', 'auto');
14+
expect(marker).toHaveAttribute('fill', '#FFF');
15+
});
16+
});

src/components/markers/marker.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { PropsWithChildren } from 'react';
2+
import { palette } from '@leafygreen-ui/palette';
3+
4+
import { DEFAULT_MARKER_SIZE } from '@/utilities/constants';
5+
6+
type Props = PropsWithChildren<React.SVGAttributes<SVGMarkerElement>>;
7+
8+
export const Marker = ({ children, id, ...rest }: Props) => {
9+
return (
10+
<marker
11+
id={id}
12+
style={{ fill: palette.gray.base }}
13+
markerHeight={DEFAULT_MARKER_SIZE}
14+
markerWidth={DEFAULT_MARKER_SIZE}
15+
refX={DEFAULT_MARKER_SIZE / 2}
16+
refY={DEFAULT_MARKER_SIZE / 2}
17+
{...rest}
18+
>
19+
{children}
20+
</marker>
21+
);
22+
};

0 commit comments

Comments
 (0)