diff --git a/README.md b/README.md
index 7d29a67..5ee86dc 100644
--- a/README.md
+++ b/README.md
@@ -100,9 +100,10 @@ export default App;
| `offset` | `number` | Optional number for space between element and start/end of stroke
| `svgContainerStyle` | `Style` | Style of the SVG container element. Useful if you want to add a z-index to your SVG container to draw the arrows under your elements, for example.
| `children` | `React.Node` |
+| `startShape` | `Object` | An object containing the props to configure the "start shape" of the arrow. Can be one of `arrow` (default) or `circle`. See [`ShapeType`](flow-typed/archer-types.js) for a complete list of available options.
| `endShape` | `Object` | An object containing the props to configure the "end shape" of the arrow. Can be one of `arrow` (default) or `circle`. See [`ShapeType`](flow-typed/archer-types.js) for a complete list of available options.
-| `startMarker` | `boolean` | Optional flag (default `false`) to also add a marker at the start of the arrow.
-| `endMarker` | `boolean` | Optional flag (default `true`) to remove the marker at the end of the arrow.
+| `enableStartMarker` | `boolean` | Optional flag (default `false`) to also add a marker at the start of the arrow.
+| `enableEndMarker` | `boolean` | Optional flag (default `true`) to remove the marker at the end of the arrow.
#### Instance methods
@@ -144,9 +145,10 @@ The `ArcherStyle` type has the following shape:
strokeDasharray: number,
noCurves: boolean,
lineStyle: string,
+ startShape: Object,
endShape: Object,
- startMarker: boolean,
- endMarker: boolean,
+ enableStartMarker: boolean,
+ enableEndMarker: boolean,
}
```
diff --git a/example/App.tsx b/example/App.tsx
index cf5ad83..8e69807 100644
--- a/example/App.tsx
+++ b/example/App.tsx
@@ -8,6 +8,7 @@ import SixthExample from './SixthExample';
import SeventhExample from './SeventhExample';
import EighthExample from './EighthExample';
import NinthExample from './NinthExample';
+import TenthExample from './TenthExample';
const getExample = (id: number) => {
switch (id) {
@@ -38,6 +39,9 @@ const getExample = (id: number) => {
case 9:
return NinthExample;
+ case 10:
+ return TenthExample;
+
default:
return SecondExample;
}
@@ -54,7 +58,7 @@ const App = () => {
Example {exampleId}
Choose an example:
- {[...Array(9).keys()].map((value) => (
+ {[...Array(10).keys()].map((value) => (
setExampleId(value + 1)}
diff --git a/example/EighthExample.tsx b/example/EighthExample.tsx
index aa9f326..23bf1f6 100644
--- a/example/EighthExample.tsx
+++ b/example/EighthExample.tsx
@@ -23,7 +23,7 @@ const FirstExample = () => {
margin: '50px',
}}
>
-
+
{
strokeColor="red"
lineStyle="straight"
offset={0}
- startMarker
- endMarker={false}
+ enableStartMarker
+ enableEndMarker={false}
>
{
+ return (
+
+
+
+
+
+ ),
+ },
+ ]}
+ >
+ Element 2
+
+
+
+ Element 3
+
+
+
+ Element 4
+
+
+
+
+ );
+};
+
+export default TenthExample;
diff --git a/src/ArcherContainer/ArcherContainer.constants.ts b/src/ArcherContainer/ArcherContainer.constants.ts
index 33aa203..71cc544 100644
--- a/src/ArcherContainer/ArcherContainer.constants.ts
+++ b/src/ArcherContainer/ArcherContainer.constants.ts
@@ -1,4 +1,4 @@
-export const endShapeDefaultProp = {
+export const shapeDefaultProp = {
arrow: {
arrowLength: 10,
arrowThickness: 6,
diff --git a/src/ArcherContainer/ArcherContainer.helpers.tsx b/src/ArcherContainer/ArcherContainer.helpers.tsx
index a32c57c..c706832 100644
--- a/src/ArcherContainer/ArcherContainer.helpers.tsx
+++ b/src/ArcherContainer/ArcherContainer.helpers.tsx
@@ -1,21 +1,26 @@
import {
- ValidShapeTypes,
+ EntityRelationType,
LineType,
- SourceToTargetType,
ShapeType,
- EntityRelationType,
+ SourceToTargetType,
+ ValidShapeTypes,
} from '../types';
import { SourceToTargetsArrayType } from './ArcherContainer.types';
const possibleShapes: Array = ['arrow', 'circle'];
-export const getEndShapeFromStyle = (shapeObj: LineType) => {
- if (!shapeObj.endShape) {
+export const getShapeStyleFromShape = (style: LineType, isStartShape: boolean) => {
+ return isStartShape ? style.startShape : style.endShape;
+};
+
+export const getShapeFromStyle = (shapeObj: LineType, isStartShape: boolean) => {
+ const shapeStyle = getShapeStyleFromShape(shapeObj, isStartShape);
+ if (!shapeStyle) {
return possibleShapes[0];
}
return (
- (Object.keys(shapeObj.endShape) as ValidShapeTypes[]).filter((key) =>
+ (Object.keys(shapeStyle) as ValidShapeTypes[]).filter((key) =>
possibleShapes.includes(key),
)[0] || possibleShapes[0]
);
@@ -34,23 +39,24 @@ export const getSourceToTargets = (
.sort((a, b) => a.order - b.order);
};
-export const createShapeObj = (style: LineType, endShape: ShapeType) => {
- const chosenEndShape = getEndShapeFromStyle(style);
+export const createShapeObj = (style: LineType, shape: ShapeType, isStartShape: boolean) => {
+ const chosenShape = getShapeFromStyle(style, isStartShape);
+ const shapeStyle = getShapeStyleFromShape(style, isStartShape);
const shapeObjMap = {
arrow: () => ({
arrow: {
- ...endShape?.arrow,
- ...style.endShape?.arrow,
+ ...shape?.arrow,
+ ...shapeStyle?.arrow,
},
}),
circle: () => ({
circle: {
- ...endShape?.circle,
- ...style.endShape?.circle,
+ ...shape?.circle,
+ ...shapeStyle?.circle,
},
}),
};
- return shapeObjMap[chosenEndShape]();
+ return shapeObjMap[chosenShape]();
};
/** Generates an id for an arrow marker
@@ -61,6 +67,7 @@ export const getMarkerId = (
uniqueId: string,
source: EntityRelationType,
target: EntityRelationType,
+ isStartShape: boolean,
): string => {
- return `${uniqueId}${source.id}${target.id}`;
+ return `${uniqueId}${source.id}${target.id}-${isStartShape ? 'start' : 'end'}`;
};
diff --git a/src/ArcherContainer/ArcherContainer.tsx b/src/ArcherContainer/ArcherContainer.tsx
index b5da4b3..edd82f2 100644
--- a/src/ArcherContainer/ArcherContainer.tsx
+++ b/src/ArcherContainer/ArcherContainer.tsx
@@ -1,16 +1,16 @@
import React, { useCallback, useImperativeHandle, useMemo, useRef, useState } from 'react';
import ResizeObserver from 'resize-observer-polyfill';
import { SourceToTargetType } from '../types';
+import { shapeDefaultProp } from './ArcherContainer.constants';
import { ArcherContainerContext, ArcherContainerContextProvider } from './ArcherContainer.context';
+import { useObserveElements, useResizeListener } from './ArcherContainer.hooks';
import {
- SourceToTargetsArrayType,
- ArcherContainerProps,
ArcherContainerHandle,
+ ArcherContainerProps,
+ SourceToTargetsArrayType,
} from './ArcherContainer.types';
-import { SvgArrows } from './components/SvgArrows';
-import { endShapeDefaultProp } from './ArcherContainer.constants';
import { ArrowMarkers } from './components/Markers';
-import { useObserveElements, useResizeListener } from './ArcherContainer.hooks';
+import { SvgArrows } from './components/SvgArrows';
const defaultSvgContainerStyle = {
position: 'absolute',
@@ -24,17 +24,18 @@ const defaultSvgContainerStyle = {
const ArcherContainer = React.forwardRef(
(
{
- endShape = endShapeDefaultProp,
+ startShape = shapeDefaultProp,
+ endShape = shapeDefaultProp,
strokeColor = '#f00',
strokeWidth = 2,
svgContainerStyle = {},
+ enableStartMarker = false,
+ enableEndMarker = true,
noCurves,
children,
className,
- endMarker,
lineStyle,
offset,
- startMarker,
strokeDasharray,
style,
}: ArcherContainerProps,
@@ -145,6 +146,9 @@ const ArcherContainer = React.forwardRef
) => React.ReactNode;
@@ -36,20 +36,25 @@ export type ArcherContainerProps = {
*/
offset?: number;
+ /**
+ * Customize the start shape of the line. Defaults to a traditional "arrow" (triangle) shape.
+ */
+ startShape?: ShapeType;
+
/**
* Customize the end shape of the line. Defaults to a traditional "arrow" (triangle) shape.
*/
endShape?: ShapeType;
/**
- * Set this to true of you want to render a marker at the start of the line
+ * Set this to true if you want to render a marker at the start of the line
*/
- startMarker?: boolean;
+ enableStartMarker?: boolean;
/**
- * Set this to false of you do not want to render a marker at the end of the line
+ * Set this to true if you want to render a marker at the end of the line
*/
- endMarker?: boolean;
+ enableEndMarker?: boolean;
/**
* Define how the line is drawn, grid for angles, straight for direct line and curve for curves
diff --git a/src/ArcherContainer/__tests__/ArcherContainer.test.tsx b/src/ArcherContainer/__tests__/ArcherContainer.test.tsx
index 65bfb9b..a845aff 100644
--- a/src/ArcherContainer/__tests__/ArcherContainer.test.tsx
+++ b/src/ArcherContainer/__tests__/ArcherContainer.test.tsx
@@ -1,8 +1,8 @@
-import React from 'react';
import { render } from '@testing-library/react';
-import ArcherContainer from '../ArcherContainer';
-import ArcherElement from '../../ArcherElement/ArcherElement';
+import React from 'react';
import { act } from 'react-dom/test-utils';
+import ArcherElement from '../../ArcherElement/ArcherElement';
+import ArcherContainer from '../ArcherContainer';
const originalConsoleWarn = console.warn;
@@ -91,7 +91,7 @@ describe('ArcherContainer', () => {
it('should render the arrow on both ends', () => {
const screen = render(
-
+
{
it('should render an arrow with className', () => {
const screen = render(
-
+
{
it('should render the arrows with labels', () => {
const screen = render(
-
+
{
it('should render the arrow only at start', () => {
const screen = render(
-
+
{
console.warn = jest.fn();
const screen = render(
-
+
{
expect.stringMatching('Could not find target element'),
);
});
+
+ it('should render the arrow at start with a circle end when provided and at end with a triangle when not provided', () => {
+ const screen = render(
+
+
+ element 1
+
+
+ element 2
+
+ ,
+ );
+ expect(screen.baseElement).toMatchSnapshot();
+ });
});
describe('Event Listeners', () => {
it('should move elements on window resize', () => {
const screen = render(
-
+
+
+
+
@@ -62,7 +76,7 @@ exports[`ArcherContainer rendering an svg with the marker element used to draw a
>
@@ -151,7 +165,21 @@ exports[`ArcherContainer rendering an svg with the marker element used to draw a
>
+
+
+
@@ -200,7 +228,7 @@ exports[`ArcherContainer rendering an svg with the marker element used to draw a
>
@@ -248,7 +276,7 @@ exports[`ArcherContainer rendering an svg with the marker element used to draw a
>
@@ -300,7 +328,7 @@ exports[`ArcherContainer rendering an svg with the marker element used to draw a
>
@@ -348,7 +376,7 @@ exports[`ArcherContainer rendering an svg with the marker element used to draw a
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ element 1
+
+
+ element 2
+
+
+
+
+