Drag from one node’s + glyph to another to create a link between them.
Create a custom link dragger while the user drags. You can then add a permanent link when the drag completes.
See also
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { Chart } from "regraph";
import { data } from "./data";
import { style } from "@ci/theme/rg/js/storyStyles";
const linkStyle = {
...style.link,
end2: { arrow: true },
};
function generateLink(id1, id2) {
return {
...linkStyle,
id1,
id2,
};
}
function generateLinkId(id1, id2, salt) {
return `${id1}_${id2}_${salt}`;
}
export const Demo = () => <CreateLink items={data} />;
function CreateLink(props) {
const { items: nodes } = props;
const [state, setState] = useState({
positions: {},
items: nodes,
originId: null,
});
const { originId, positions } = state;
const handleDragStart = ({ id: nextOriginId, subItem, setDragOptions }) => {
if (subItem && subItem.type === "glyph" && subItem.index === 0) {
// Save the id of the node that initiated the drag
setState((current) => {
return { ...current, originId: nextOriginId };
});
setDragOptions({
// Create a temporary link dragger
dummyLink: linkStyle,
});
}
};
const handleDragEnd = ({ id }) => {
if (!originId || id === originId) {
return;
}
setState((current) => {
// Create a new link between the origin and target items
const newLinkId = generateLinkId(originId, id, Object.keys(current.items).length);
const newLink = generateLink(originId, id);
return {
...current,
items: { ...current.items, [newLinkId]: newLink },
originId: null,
};
});
};
const handleChange = ({ positions: nextPositions }) => {
if (nextPositions) {
setState((current) => {
return { ...current, positions: nextPositions };
});
}
};
const { items } = state;
return (
<Chart
animation={{ animate: false, time: 0 }}
items={items}
positions={positions}
options={{
fit: "none",
navigation: false,
overview: false,
}}
onChange={handleChange}
onDragEnd={handleDragEnd}
onDragStart={handleDragStart}
/>
);
}
const root = createRoot(document.getElementById("regraph"));
root.render(<Demo />); import { style } from "@ci/theme/rg/js/storyStyles";
const glyph = {
...style.primary3,
label: {
...style.primaryLabel3,
bold: true,
center: true,
text: "+",
},
size: 1.2,
};
const label = {
...style.primaryLabel1,
text: "Drag from +",
};
export const data = {
a: {
label,
...style.primary1,
glyphs: [glyph],
},
b: {
label,
...style.primary1,
glyphs: [glyph],
},
}; <!doctype html>
<html>
<body>
<div id="regraph" style="height: 100vh"></div>
<script type="module" src="./code.jsx"></script>
</body>
</html>