diff --git a/demo/Fragmentation.tsx b/demo/Fragmentation.tsx
index 54f71a3..ea87877 100644
--- a/demo/Fragmentation.tsx
+++ b/demo/Fragmentation.tsx
@@ -16,12 +16,13 @@ const props = {
nodeRenderer: moleculeRenderer,
arrowRendererOptions: {
getLabel: (node) => {
- return node?.reaction?.label;
+ return `Hello\n${node?.reaction?.label}\nWorld`;
},
+ verticalPosition: 'top',
getID: () => {
return Math.random().toString();
},
- labelPosition: 'center',
+ horizontalPosition: 'left',
},
nodeRendererOptions: {
getID: () => {
diff --git a/src/__tests__/__snapshots__/molecule.test.tsx.snap b/src/__tests__/__snapshots__/molecule.test.tsx.snap
index b0171e1..0b5c496 100644
--- a/src/__tests__/__snapshots__/molecule.test.tsx.snap
+++ b/src/__tests__/__snapshots__/molecule.test.tsx.snap
@@ -685,5 +685,5 @@ exports[`render: Molecule 1`] = `
-"
+"
`;
diff --git a/src/__tests__/molecule.test.tsx b/src/__tests__/molecule.test.tsx
index b6da879..216327c 100644
--- a/src/__tests__/molecule.test.tsx
+++ b/src/__tests__/molecule.test.tsx
@@ -29,7 +29,7 @@ test('render: Molecule', () => {
getLabel: (node) => {
return node.transformation;
},
- labelPosition: 'center',
+ horizontalPosition: 'center',
},
positionOptions: {
spacingHorizontal: 150,
diff --git a/src/components/Arrow.tsx b/src/components/Arrow.tsx
index 32ba306..d70401f 100644
--- a/src/components/Arrow.tsx
+++ b/src/components/Arrow.tsx
@@ -1,8 +1,7 @@
import { Point } from '../types/Point';
-import { CenteredText } from './CenteredText';
import { refX } from './MarkerDef.utils';
-import { RightText } from './RightText';
+import { Text } from './Text';
/**
* Creates a simple arrow between 2 points. The arrow has one inflection point, which is the middle of the line.
* The SVG must define a marker with id="arrowhead" for this to work.
@@ -15,9 +14,17 @@ export function Arrow(props: {
from: Point;
to: Point;
label: string;
- labelPosition: 'center' | 'right';
+ horizontalPosition: 'left' | 'center' | 'right';
+ verticalPosition?: 'top' | 'bottom' | 'center';
}) {
- const { id, from, to, label, labelPosition = 'center' } = props;
+ const {
+ id,
+ from,
+ to,
+ label,
+ horizontalPosition = 'center',
+ verticalPosition = 'center',
+ } = props;
const middle = { x: (from.x + to.x) / 2, y: (from.y + to.y) / 2 };
const headInflectionPoint = {
@@ -37,11 +44,32 @@ export function Arrow(props: {
markerEnd: 'url(#arrowhead)',
}}
/>
- {labelPosition === 'center' && (
-
+ {horizontalPosition === 'center' && (
+
)}
- {labelPosition === 'right' && (
-
+ {horizontalPosition === 'right' && (
+
+ )}
+ {horizontalPosition === 'left' && (
+
)}
);
diff --git a/src/components/CenteredText.tsx b/src/components/CenteredText.tsx
deleted file mode 100644
index 0bdb327..0000000
--- a/src/components/CenteredText.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-export function CenteredText(props: { x: number; y: number; label: string }) {
- const { x, y, label } = props;
- const labelPosition = `translate(${x},${y})`;
- return (
- <>
-
- {label}
-
-
- {label}
-
- >
- );
-}
diff --git a/src/components/MultilineText.tsx b/src/components/MultilineText.tsx
new file mode 100644
index 0000000..f40c314
--- /dev/null
+++ b/src/components/MultilineText.tsx
@@ -0,0 +1,23 @@
+export function MultilineText(props: {
+ label: string;
+ verticalPosition: 'top' | 'center' | 'bottom';
+}) {
+ const { label, verticalPosition } = props;
+ if (!label) return;
+ const lines = label.split(/\r?\n/);
+ const firstDX =
+ verticalPosition === 'top'
+ ? 1
+ : verticalPosition === 'center'
+ ? -lines.length / 2 + 0.5
+ : -lines.length;
+ return (
+ <>
+ {lines.map((line, index) => (
+
+ {line}
+
+ ))}
+ >
+ );
+}
diff --git a/src/components/RightText.tsx b/src/components/RightText.tsx
deleted file mode 100644
index 1d7a8f5..0000000
--- a/src/components/RightText.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-export function RightText(props: { x: number; y: number; label: string }) {
- const { x, y, label } = props;
- const labelPosition = `translate(${x},${y})`;
- return (
- <>
-
- {label}
-
-
- {label}
-
- >
- );
-}
diff --git a/src/components/Text.tsx b/src/components/Text.tsx
new file mode 100644
index 0000000..9e73856
--- /dev/null
+++ b/src/components/Text.tsx
@@ -0,0 +1,51 @@
+import { MultilineText } from './MultilineText';
+
+export function Text(props: {
+ x: number;
+ y: number;
+ label: string;
+ horizontalPosition: 'left' | 'center' | 'right';
+ verticalPosition: 'top' | 'center' | 'bottom';
+}) {
+ const { x, y, label, verticalPosition, horizontalPosition } = props;
+ const transform = `translate(${x},${y})`;
+
+ let textAnchor;
+ switch (horizontalPosition) {
+ case 'left':
+ textAnchor = 'start';
+ break;
+ case 'center':
+ textAnchor = 'middle';
+ break;
+ case 'right':
+ textAnchor = 'end';
+ break;
+ default:
+ textAnchor = 'middle';
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/data/getArrows.tsx b/src/data/getArrows.tsx
index 783594b..0f35121 100644
--- a/src/data/getArrows.tsx
+++ b/src/data/getArrows.tsx
@@ -8,7 +8,7 @@ export function getArrows(nodes, options = {}) {
}
function getArrowsSS(nodes, arrows, status, options: any = {}) {
- const { getLabel, labelPosition, getID } = options;
+ const { getLabel, horizontalPosition, getID, verticalPosition } = options;
for (const node of nodes) {
if (node.children) {
@@ -20,7 +20,8 @@ function getArrowsSS(nodes, arrows, status, options: any = {}) {
from={node.anchor.right}
to={child.anchor.left}
label={getLabel?.(child)}
- labelPosition={labelPosition}
+ horizontalPosition={horizontalPosition}
+ verticalPosition={verticalPosition}
/>,
);
}
diff --git a/test/index.html b/test/index.html
index a458644..360914c 100644
--- a/test/index.html
+++ b/test/index.html
@@ -1,69 +1,71 @@
-
-
-
-
-
-
-
-
+
- const responseTaxonomies = await fetch('data/taxonomies.json');
- const dataTaxonomies = await responseTaxonomies.json();
- const svgTaxonomies = TreeSVG.render(dataTaxonomies, {
- nodeRenderer: 'taxonomy',
- rankDepthOptions: {
- maxRankDepth: 8,
- },
- positionOptions: {
- spacingHorizontal: 100,
- },
- });
- const responseTrees = await fetch('data/trees.json');
- const dataTrees = await responseTrees.json();
- const svgTrees = TreeSVG.render(dataTrees, {
- nodeRenderer: 'trees',
- nodeRendererOptions: {
- masses: [
- 58.065, 105.0697, 133.0647, 135.0439, 163.0752, 194.1173, 530.15,
- ],
- precision: 50,
- numberFormat: '0.0000',
- },
- positionOptions: {
- spacingHorizontal: 150,
- },
- });
- document.getElementById('react-tree-svg').innerHTML = svg;
- document.getElementById('taxonomies-graph').innerHTML = svgTaxonomies;
- document.getElementById('trees-graph').innerHTML = svgTrees;
- }
- getMolecules();
- function handleClick(event) {
- const target = event.target;
- console.log(target);
- if (target.tagName === 'text') {
- const url = target.getAttribute('data-url');
- if (url) {
- window.open(url, '_blank');
- }
+
+
+
+
+
-
-
+ }
+
+