Merge pull request #207 from wbkd/feat-edgetext

feat(edges): add label and labelBg options
This commit is contained in:
Moritz
2020-05-11 12:22:54 +02:00
committed by GitHub
24 changed files with 406 additions and 74 deletions
+8 -2
View File
@@ -130,7 +130,7 @@ You can find an example of how to implement a custom node in the [custom node ex
There are three [edge types](#edge-types--custom-edges) (`straight`, `default`, `step`) you can use. The default type is `default`. You can also create [custom edges](#edge-types--custom-edges). There are three [edge types](#edge-types--custom-edges) (`straight`, `default`, `step`) you can use. The default type is `default`. You can also create [custom edges](#edge-types--custom-edges).
Edge example: `{ id: 'e1-2', type: 'straight', source: '1', target: '2', animated: true }` Edge example: `{ id: 'e1-2', type: 'straight', source: '1', target: '2', animated: true, label: 'edge label' }`
### Props ### Props
@@ -139,7 +139,13 @@ Edge example: `{ id: 'e1-2', type: 'straight', source: '1', target: '2', animate
- `target`: string (an id of a node) *(required)* - `target`: string (an id of a node) *(required)*
- `type`: 'input' | 'output' | 'default' or a custom one you implemented - `type`: 'input' | 'output' | 'default' or a custom one you implemented
- `animated`: boolean - `animated`: boolean
- `style`: css properties - `style`: css properties for the edge line path
- `label`: string
- `labelStyle`: css properties for the text
- `labelShowBg`: boolean - default: `true`
- `labelBgStyle`: css properties for the text background
You can find an example with lots of different edges in the [edges example](https://react-flow.netlify.app/edges).
### Edge Types / Custom Edges ### Edge Types / Custom Edges
+51 -12
View File
@@ -6896,7 +6896,7 @@ function renderEdge(edge, props, nodes, selectedElements, isInteractive) {
var targetPosition = targetHandle ? targetHandle.position : Position.Top; var targetPosition = targetHandle ? targetHandle.position : Position.Top;
var _c = getEdgePositions(sourceNode, sourceHandle, sourcePosition, targetNode, targetHandle, targetPosition), sourceX = _c.sourceX, sourceY = _c.sourceY, targetX = _c.targetX, targetY = _c.targetY; var _c = getEdgePositions(sourceNode, sourceHandle, sourcePosition, targetNode, targetHandle, targetPosition), sourceX = _c.sourceX, sourceY = _c.sourceY, targetX = _c.targetX, targetY = _c.targetY;
var isSelected = selectedElements.some(function (elm) { return isEdge(elm) && elm.source === sourceId && elm.target === targetId; }); var isSelected = selectedElements.some(function (elm) { return isEdge(elm) && elm.source === sourceId && elm.target === targetId; });
return (React__default.createElement(EdgeComponent, { key: edge.id, id: edge.id, type: edge.type, onClick: props.onElementClick, selected: isSelected, animated: edge.animated, style: edge.style, source: sourceId, target: targetId, sourceHandleId: sourceHandleId, targetHandleId: targetHandleId, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, isInteractive: isInteractive })); return (React__default.createElement(EdgeComponent, { key: edge.id, id: edge.id, type: edge.type, onClick: props.onElementClick, selected: isSelected, animated: edge.animated, label: edge.label, labelStyle: edge.labelStyle, labelShowBg: edge.labelShowBg, labelBgStyle: edge.labelBgStyle, style: edge.style, source: sourceId, target: targetId, sourceHandleId: sourceHandleId, targetHandleId: targetHandleId, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, isInteractive: isInteractive }));
} }
var EdgeRenderer = memo(function (props) { var EdgeRenderer = memo(function (props) {
var _a = useStoreState$1(function (s) { return ({ var _a = useStoreState$1(function (s) { return ({
@@ -9270,38 +9270,77 @@ function createNodeTypes(nodeTypes) {
return __assign(__assign({}, standardTypes), specialTypes); return __assign(__assign({}, standardTypes), specialTypes);
} }
var textBgPadding = 2;
var EdgeText = memo(function (_a) {
var x = _a.x, y = _a.y, label = _a.label, _b = _a.labelStyle, labelStyle = _b === void 0 ? {} : _b, _c = _a.labelShowBg, labelShowBg = _c === void 0 ? true : _c, _d = _a.labelBgStyle, labelBgStyle = _d === void 0 ? {} : _d;
var edgeRef = useRef(null);
var _e = useState({ x: 0, y: 0, width: 0, height: 0 }), edgeTextBbox = _e[0], setEdgeTextBbox = _e[1];
useEffect(function () {
if (edgeRef.current) {
var textBbox = edgeRef.current.getBBox();
setEdgeTextBbox({
x: textBbox.x,
y: textBbox.y,
width: textBbox.width,
height: textBbox.height,
});
}
}, []);
if (typeof label === 'undefined' || !label) {
return null;
}
return (React__default.createElement("g", { transform: "translate(" + (x - edgeTextBbox.width / 2) + " " + (y - edgeTextBbox.height / 2) + ")" },
labelShowBg && (React__default.createElement("rect", { width: edgeTextBbox.width + 2 * textBgPadding, x: -textBgPadding, y: -textBgPadding, height: edgeTextBbox.height + 2 * textBgPadding, className: "react-flow__edge-textbg", style: labelBgStyle })),
React__default.createElement("text", { className: "react-flow__edge-text", y: edgeTextBbox.height / 2, dy: "0.3em", ref: edgeRef, style: labelStyle }, label)));
});
var BezierEdge = memo(function (_a) { var BezierEdge = memo(function (_a) {
var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, _b = _a.sourcePosition, sourcePosition = _b === void 0 ? Position.Bottom : _b, _c = _a.targetPosition, targetPosition = _c === void 0 ? Position.Top : _c, _d = _a.style, style = _d === void 0 ? {} : _d; var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, _b = _a.sourcePosition, sourcePosition = _b === void 0 ? Position.Bottom : _b, _c = _a.targetPosition, targetPosition = _c === void 0 ? Position.Top : _c, label = _a.label, labelStyle = _a.labelStyle, labelShowBg = _a.labelShowBg, labelBgStyle = _a.labelBgStyle, _d = _a.style, style = _d === void 0 ? {} : _d;
var yOffset = Math.abs(targetY - sourceY) / 2; var yOffset = Math.abs(targetY - sourceY) / 2;
var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset; var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
var xOffset = Math.abs(targetX - sourceX) / 2;
var centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
var dAttr = "M" + sourceX + "," + sourceY + " C" + sourceX + "," + centerY + " " + targetX + "," + centerY + " " + targetX + "," + targetY; var dAttr = "M" + sourceX + "," + sourceY + " C" + sourceX + "," + centerY + " " + targetX + "," + centerY + " " + targetX + "," + targetY;
var leftAndRight = [Position.Left, Position.Right]; var leftAndRight = [Position.Left, Position.Right];
if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) { if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
var xOffset = Math.abs(targetX - sourceX) / 2;
var centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
dAttr = "M" + sourceX + "," + sourceY + " C" + centerX + "," + sourceY + " " + centerX + "," + targetY + " " + targetX + "," + targetY; dAttr = "M" + sourceX + "," + sourceY + " C" + centerX + "," + sourceY + " " + centerX + "," + targetY + " " + targetX + "," + targetY;
} }
else if (leftAndRight.includes(sourcePosition) || leftAndRight.includes(targetPosition)) { else if (leftAndRight.includes(sourcePosition) || leftAndRight.includes(targetPosition)) {
dAttr = "M" + sourceX + "," + sourceY + " C" + sourceX + "," + targetY + " " + sourceX + "," + targetY + " " + targetX + "," + targetY; dAttr = "M" + sourceX + "," + sourceY + " C" + sourceX + "," + targetY + " " + sourceX + "," + targetY + " " + targetX + "," + targetY;
} }
return React__default.createElement("path", __assign({}, style, { d: dAttr })); var text = label ? (React__default.createElement(EdgeText, { x: centerX, y: centerY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle })) : null;
return (React__default.createElement("g", null,
React__default.createElement("path", { style: style, d: dAttr, className: "react-flow__edge-path" }),
text));
}); });
var StraightEdge = memo(function (_a) { var StraightEdge = memo(function (_a) {
var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, _b = _a.style, style = _b === void 0 ? {} : _b; var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, label = _a.label, labelStyle = _a.labelStyle, labelShowBg = _a.labelShowBg, labelBgStyle = _a.labelBgStyle, _b = _a.style, style = _b === void 0 ? {} : _b;
return (React__default.createElement("path", __assign({}, style, { d: "M " + sourceX + "," + sourceY + "L " + targetX + "," + targetY }))); var yOffset = Math.abs(targetY - sourceY) / 2;
var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
var xOffset = Math.abs(targetX - sourceX) / 2;
var centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
var text = label ? (React__default.createElement(EdgeText, { x: centerX, y: centerY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle })) : null;
return (React__default.createElement("g", null,
React__default.createElement("path", { style: style, className: "react-flow__edge-path", d: "M " + sourceX + "," + sourceY + "L " + targetX + "," + targetY }),
text));
}); });
var StepEdge = memo(function (_a) { var StepEdge = memo(function (_a) {
var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, _b = _a.style, style = _b === void 0 ? {} : _b; var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, label = _a.label, labelStyle = _a.labelStyle, labelShowBg = _a.labelShowBg, labelBgStyle = _a.labelBgStyle, _b = _a.style, style = _b === void 0 ? {} : _b;
var yOffset = Math.abs(targetY - sourceY) / 2; var yOffset = Math.abs(targetY - sourceY) / 2;
var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset; var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
return (React__default.createElement("path", __assign({}, style, { d: "M " + sourceX + "," + sourceY + "L " + sourceX + "," + centerY + "L " + targetX + "," + centerY + "L " + targetX + "," + targetY }))); var xOffset = Math.abs(targetX - sourceX) / 2;
var centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
var text = label ? (React__default.createElement(EdgeText, { x: centerX, y: centerY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle })) : null;
return (React__default.createElement("g", null,
React__default.createElement("path", { style: style, className: "react-flow__edge-path", d: "M " + sourceX + "," + sourceY + "L " + sourceX + "," + centerY + "L " + targetX + "," + centerY + "L " + targetX + "," + targetY }),
text));
}); });
var wrapEdge = (function (EdgeComponent) { var wrapEdge = (function (EdgeComponent) {
var EdgeWrapper = memo(function (_a) { var EdgeWrapper = memo(function (_a) {
var id = _a.id, source = _a.source, target = _a.target, type = _a.type, animated = _a.animated, selected = _a.selected, onClick = _a.onClick, isInteractive = _a.isInteractive, rest = __rest(_a, ["id", "source", "target", "type", "animated", "selected", "onClick", "isInteractive"]); var id = _a.id, source = _a.source, target = _a.target, type = _a.type, animated = _a.animated, selected = _a.selected, onClick = _a.onClick, isInteractive = _a.isInteractive, label = _a.label, labelStyle = _a.labelStyle, labelShowBg = _a.labelShowBg, labelBgStyle = _a.labelBgStyle, rest = __rest(_a, ["id", "source", "target", "type", "animated", "selected", "onClick", "isInteractive", "label", "labelStyle", "labelShowBg", "labelBgStyle"]);
var edgeClasses = classnames('react-flow__edge', { selected: selected, animated: animated }); var edgeClasses = classnames('react-flow__edge', { selected: selected, animated: animated });
var onEdgeClick = function () { var onEdgeClick = function () {
if (!isInteractive) { if (!isInteractive) {
@@ -9311,7 +9350,7 @@ var wrapEdge = (function (EdgeComponent) {
onClick({ id: id, source: source, target: target, type: type }); onClick({ id: id, source: source, target: target, type: type });
}; };
return (React__default.createElement("g", { className: edgeClasses, onClick: onEdgeClick }, return (React__default.createElement("g", { className: edgeClasses, onClick: onEdgeClick },
React__default.createElement(EdgeComponent, __assign({ id: id, source: source, target: target, type: type, animated: animated, selected: selected, onClick: onClick }, rest)))); React__default.createElement(EdgeComponent, __assign({ id: id, source: source, target: target, type: type, animated: animated, selected: selected, onClick: onClick, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle }, rest))));
}); });
EdgeWrapper.displayName = 'EdgeWrapper'; EdgeWrapper.displayName = 'EdgeWrapper';
return EdgeWrapper; return EdgeWrapper;
@@ -9359,7 +9398,7 @@ function styleInject(css, ref) {
} }
} }
var css_248z = ".react-flow {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.react-flow__renderer {\n width: 100%;\n height: 100%;\n position: absolute;\n}\n\n.react-flow__zoompane {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1;\n}\n\n.react-flow__selectionpane {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2;\n}\n\n.react-flow__selection {\n position: absolute;\n top: 0;\n left: 0;\n background: rgba(0, 89, 220, 0.08);\n border: 1px dotted rgba(0, 89, 220, 0.8);\n}\n\n.react-flow__edges {\n position: absolute;\n top: 0;\n left: 0;\n pointer-events: none;\n z-index: 2;\n}\n\n.react-flow__edge {\n fill: none;\n stroke: #bbb;\n stroke-width: 2;\n pointer-events: all;\n}\n\n.react-flow__edge.selected {\n stroke: #555;\n }\n\n.react-flow__edge.animated {\n stroke-dasharray: 5;\n -webkit-animation: dashdraw 0.5s linear infinite;\n animation: dashdraw 0.5s linear infinite;\n }\n\n.react-flow__edge.connection {\n stroke: '#ddd';\n pointer-events: none;\n }\n\n@-webkit-keyframes dashdraw {\n from {\n stroke-dashoffset: 10;\n }\n}\n\n@keyframes dashdraw {\n from {\n stroke-dashoffset: 10;\n }\n}\n\n.react-flow__nodes {\n width: 100%;\n height: 100%;\n position: absolute;\n z-index: 3;\n pointer-events: none;\n transform-origin: 0 0;\n}\n\n.is-interactive .react-flow__node {\n cursor: -webkit-grab;\n cursor: grab;\n }\n\n.is-interactive .react-flow__node:hover > * {\n box-shadow: 0 1px 5px 2px rgba(0, 0, 0, 0.08);\n }\n\n.is-interactive .react-flow__handle {\n cursor: crosshair;\n }\n\n.react-flow__node {\n position: absolute;\n color: #222;\n font-family: sans-serif;\n font-size: 12px;\n text-align: center;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n pointer-events: all;\n transform-origin: 0 0;\n}\n\n.react-flow__node.selected > * {\n box-shadow: 0 0 0 2px #555;\n }\n\n.react-flow__handle {\n position: absolute;\n width: 10px;\n height: 8px;\n background: rgba(255, 255, 255, 0.4);\n}\n\n.react-flow__handle.bottom {\n top: auto;\n left: 50%;\n bottom: 0;\n transform: translate(-50%, 0);\n }\n\n.react-flow__handle.top {\n left: 50%;\n top: 0;\n transform: translate(-50%, 0);\n }\n\n.react-flow__handle.left {\n top: 50%;\n left: 0;\n transform: translate(0, -50%);\n }\n\n.react-flow__handle.right {\n right: 0;\n top: 50%;\n transform: translate(0, -50%);\n }\n\n.react-flow__nodesselection {\n z-index: 3;\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n transform-origin: left top;\n pointer-events: none;\n}\n\n.react-flow__nodesselection-rect {\n position: absolute;\n background: rgba(0, 89, 220, 0.08);\n border: 1px dotted rgba(0, 89, 220, 0.8);\n pointer-events: all;\n }\n\n.react-flow__controls {\n box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.08);\n}\n\n.react-flow__controls-button {\n background: #fefefe;\n border-bottom: 1px solid #eee;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 16px;\n height: 16px;\n cursor: pointer;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n padding: 5px;\n }\n\n.react-flow__controls-button svg {\n width: 100%;\n }\n\n.react-flow__controls-button:hover {\n background: #f4f4f4;\n }\n"; var css_248z = ".react-flow {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.react-flow__renderer {\n width: 100%;\n height: 100%;\n position: absolute;\n}\n\n.react-flow__zoompane {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1;\n}\n\n.react-flow__selectionpane {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2;\n}\n\n.react-flow__selection {\n position: absolute;\n top: 0;\n left: 0;\n background: rgba(0, 89, 220, 0.08);\n border: 1px dotted rgba(0, 89, 220, 0.8);\n}\n\n.react-flow__edges {\n position: absolute;\n top: 0;\n left: 0;\n pointer-events: none;\n z-index: 2;\n}\n\n.react-flow__edge {\n pointer-events: all;\n}\n\n.react-flow__edge.animated path {\n stroke-dasharray: 5;\n -webkit-animation: dashdraw 0.5s linear infinite;\n animation: dashdraw 0.5s linear infinite;\n }\n\n.react-flow__edge.connection {\n stroke: '#ddd';\n pointer-events: none;\n }\n\n.react-flow__edge-path {\n fill: none;\n stroke: #bbb;\n stroke-width: 2;\n}\n\n.react-flow__edge-path.selected {\n stroke: #555;\n }\n\n.react-flow__edge-text {\n font-size: 12px;\n pointer-events: none;\n}\n\n.react-flow__edge-textbg {\n fill: white;\n}\n\n@-webkit-keyframes dashdraw {\n from {\n stroke-dashoffset: 10;\n }\n}\n\n@keyframes dashdraw {\n from {\n stroke-dashoffset: 10;\n }\n}\n\n.react-flow__nodes {\n width: 100%;\n height: 100%;\n position: absolute;\n z-index: 3;\n pointer-events: none;\n transform-origin: 0 0;\n}\n\n.is-interactive .react-flow__node {\n cursor: -webkit-grab;\n cursor: grab;\n }\n\n.is-interactive .react-flow__node:hover > * {\n box-shadow: 0 1px 5px 2px rgba(0, 0, 0, 0.08);\n }\n\n.is-interactive .react-flow__handle {\n cursor: crosshair;\n }\n\n.react-flow__node {\n position: absolute;\n color: #222;\n font-family: sans-serif;\n font-size: 12px;\n text-align: center;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n pointer-events: all;\n transform-origin: 0 0;\n}\n\n.react-flow__node.selected > * {\n box-shadow: 0 0 0 2px #555;\n }\n\n.react-flow__handle {\n position: absolute;\n width: 10px;\n height: 8px;\n background: rgba(255, 255, 255, 0.4);\n}\n\n.react-flow__handle.bottom {\n top: auto;\n left: 50%;\n bottom: 0;\n transform: translate(-50%, 0);\n }\n\n.react-flow__handle.top {\n left: 50%;\n top: 0;\n transform: translate(-50%, 0);\n }\n\n.react-flow__handle.left {\n top: 50%;\n left: 0;\n transform: translate(0, -50%);\n }\n\n.react-flow__handle.right {\n right: 0;\n top: 50%;\n transform: translate(0, -50%);\n }\n\n.react-flow__nodesselection {\n z-index: 3;\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n transform-origin: left top;\n pointer-events: none;\n}\n\n.react-flow__nodesselection-rect {\n position: absolute;\n background: rgba(0, 89, 220, 0.08);\n border: 1px dotted rgba(0, 89, 220, 0.8);\n pointer-events: all;\n }\n\n.react-flow__controls {\n box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.08);\n}\n\n.react-flow__controls-button {\n background: #fefefe;\n border-bottom: 1px solid #eee;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 16px;\n height: 16px;\n cursor: pointer;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n padding: 5px;\n }\n\n.react-flow__controls-button svg {\n width: 100%;\n }\n\n.react-flow__controls-button:hover {\n background: #f4f4f4;\n }\n";
styleInject(css_248z); styleInject(css_248z);
var ReactFlow = function (_a) { var ReactFlow = function (_a) {
+1 -1
View File
File diff suppressed because one or more lines are too long
+51 -12
View File
@@ -6903,7 +6903,7 @@ function renderEdge(edge, props, nodes, selectedElements, isInteractive) {
var targetPosition = targetHandle ? targetHandle.position : Position.Top; var targetPosition = targetHandle ? targetHandle.position : Position.Top;
var _c = getEdgePositions(sourceNode, sourceHandle, sourcePosition, targetNode, targetHandle, targetPosition), sourceX = _c.sourceX, sourceY = _c.sourceY, targetX = _c.targetX, targetY = _c.targetY; var _c = getEdgePositions(sourceNode, sourceHandle, sourcePosition, targetNode, targetHandle, targetPosition), sourceX = _c.sourceX, sourceY = _c.sourceY, targetX = _c.targetX, targetY = _c.targetY;
var isSelected = selectedElements.some(function (elm) { return isEdge(elm) && elm.source === sourceId && elm.target === targetId; }); var isSelected = selectedElements.some(function (elm) { return isEdge(elm) && elm.source === sourceId && elm.target === targetId; });
return (React__default.createElement(EdgeComponent, { key: edge.id, id: edge.id, type: edge.type, onClick: props.onElementClick, selected: isSelected, animated: edge.animated, style: edge.style, source: sourceId, target: targetId, sourceHandleId: sourceHandleId, targetHandleId: targetHandleId, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, isInteractive: isInteractive })); return (React__default.createElement(EdgeComponent, { key: edge.id, id: edge.id, type: edge.type, onClick: props.onElementClick, selected: isSelected, animated: edge.animated, label: edge.label, labelStyle: edge.labelStyle, labelShowBg: edge.labelShowBg, labelBgStyle: edge.labelBgStyle, style: edge.style, source: sourceId, target: targetId, sourceHandleId: sourceHandleId, targetHandleId: targetHandleId, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, isInteractive: isInteractive }));
} }
var EdgeRenderer = React.memo(function (props) { var EdgeRenderer = React.memo(function (props) {
var _a = useStoreState$1(function (s) { return ({ var _a = useStoreState$1(function (s) { return ({
@@ -9277,38 +9277,77 @@ function createNodeTypes(nodeTypes) {
return __assign(__assign({}, standardTypes), specialTypes); return __assign(__assign({}, standardTypes), specialTypes);
} }
var textBgPadding = 2;
var EdgeText = React.memo(function (_a) {
var x = _a.x, y = _a.y, label = _a.label, _b = _a.labelStyle, labelStyle = _b === void 0 ? {} : _b, _c = _a.labelShowBg, labelShowBg = _c === void 0 ? true : _c, _d = _a.labelBgStyle, labelBgStyle = _d === void 0 ? {} : _d;
var edgeRef = React.useRef(null);
var _e = React.useState({ x: 0, y: 0, width: 0, height: 0 }), edgeTextBbox = _e[0], setEdgeTextBbox = _e[1];
React.useEffect(function () {
if (edgeRef.current) {
var textBbox = edgeRef.current.getBBox();
setEdgeTextBbox({
x: textBbox.x,
y: textBbox.y,
width: textBbox.width,
height: textBbox.height,
});
}
}, []);
if (typeof label === 'undefined' || !label) {
return null;
}
return (React__default.createElement("g", { transform: "translate(" + (x - edgeTextBbox.width / 2) + " " + (y - edgeTextBbox.height / 2) + ")" },
labelShowBg && (React__default.createElement("rect", { width: edgeTextBbox.width + 2 * textBgPadding, x: -textBgPadding, y: -textBgPadding, height: edgeTextBbox.height + 2 * textBgPadding, className: "react-flow__edge-textbg", style: labelBgStyle })),
React__default.createElement("text", { className: "react-flow__edge-text", y: edgeTextBbox.height / 2, dy: "0.3em", ref: edgeRef, style: labelStyle }, label)));
});
var BezierEdge = React.memo(function (_a) { var BezierEdge = React.memo(function (_a) {
var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, _b = _a.sourcePosition, sourcePosition = _b === void 0 ? Position.Bottom : _b, _c = _a.targetPosition, targetPosition = _c === void 0 ? Position.Top : _c, _d = _a.style, style = _d === void 0 ? {} : _d; var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, _b = _a.sourcePosition, sourcePosition = _b === void 0 ? Position.Bottom : _b, _c = _a.targetPosition, targetPosition = _c === void 0 ? Position.Top : _c, label = _a.label, labelStyle = _a.labelStyle, labelShowBg = _a.labelShowBg, labelBgStyle = _a.labelBgStyle, _d = _a.style, style = _d === void 0 ? {} : _d;
var yOffset = Math.abs(targetY - sourceY) / 2; var yOffset = Math.abs(targetY - sourceY) / 2;
var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset; var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
var xOffset = Math.abs(targetX - sourceX) / 2;
var centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
var dAttr = "M" + sourceX + "," + sourceY + " C" + sourceX + "," + centerY + " " + targetX + "," + centerY + " " + targetX + "," + targetY; var dAttr = "M" + sourceX + "," + sourceY + " C" + sourceX + "," + centerY + " " + targetX + "," + centerY + " " + targetX + "," + targetY;
var leftAndRight = [Position.Left, Position.Right]; var leftAndRight = [Position.Left, Position.Right];
if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) { if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
var xOffset = Math.abs(targetX - sourceX) / 2;
var centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
dAttr = "M" + sourceX + "," + sourceY + " C" + centerX + "," + sourceY + " " + centerX + "," + targetY + " " + targetX + "," + targetY; dAttr = "M" + sourceX + "," + sourceY + " C" + centerX + "," + sourceY + " " + centerX + "," + targetY + " " + targetX + "," + targetY;
} }
else if (leftAndRight.includes(sourcePosition) || leftAndRight.includes(targetPosition)) { else if (leftAndRight.includes(sourcePosition) || leftAndRight.includes(targetPosition)) {
dAttr = "M" + sourceX + "," + sourceY + " C" + sourceX + "," + targetY + " " + sourceX + "," + targetY + " " + targetX + "," + targetY; dAttr = "M" + sourceX + "," + sourceY + " C" + sourceX + "," + targetY + " " + sourceX + "," + targetY + " " + targetX + "," + targetY;
} }
return React__default.createElement("path", __assign({}, style, { d: dAttr })); var text = label ? (React__default.createElement(EdgeText, { x: centerX, y: centerY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle })) : null;
return (React__default.createElement("g", null,
React__default.createElement("path", { style: style, d: dAttr, className: "react-flow__edge-path" }),
text));
}); });
var StraightEdge = React.memo(function (_a) { var StraightEdge = React.memo(function (_a) {
var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, _b = _a.style, style = _b === void 0 ? {} : _b; var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, label = _a.label, labelStyle = _a.labelStyle, labelShowBg = _a.labelShowBg, labelBgStyle = _a.labelBgStyle, _b = _a.style, style = _b === void 0 ? {} : _b;
return (React__default.createElement("path", __assign({}, style, { d: "M " + sourceX + "," + sourceY + "L " + targetX + "," + targetY }))); var yOffset = Math.abs(targetY - sourceY) / 2;
var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
var xOffset = Math.abs(targetX - sourceX) / 2;
var centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
var text = label ? (React__default.createElement(EdgeText, { x: centerX, y: centerY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle })) : null;
return (React__default.createElement("g", null,
React__default.createElement("path", { style: style, className: "react-flow__edge-path", d: "M " + sourceX + "," + sourceY + "L " + targetX + "," + targetY }),
text));
}); });
var StepEdge = React.memo(function (_a) { var StepEdge = React.memo(function (_a) {
var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, _b = _a.style, style = _b === void 0 ? {} : _b; var sourceX = _a.sourceX, sourceY = _a.sourceY, targetX = _a.targetX, targetY = _a.targetY, label = _a.label, labelStyle = _a.labelStyle, labelShowBg = _a.labelShowBg, labelBgStyle = _a.labelBgStyle, _b = _a.style, style = _b === void 0 ? {} : _b;
var yOffset = Math.abs(targetY - sourceY) / 2; var yOffset = Math.abs(targetY - sourceY) / 2;
var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset; var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
return (React__default.createElement("path", __assign({}, style, { d: "M " + sourceX + "," + sourceY + "L " + sourceX + "," + centerY + "L " + targetX + "," + centerY + "L " + targetX + "," + targetY }))); var xOffset = Math.abs(targetX - sourceX) / 2;
var centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
var text = label ? (React__default.createElement(EdgeText, { x: centerX, y: centerY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle })) : null;
return (React__default.createElement("g", null,
React__default.createElement("path", { style: style, className: "react-flow__edge-path", d: "M " + sourceX + "," + sourceY + "L " + sourceX + "," + centerY + "L " + targetX + "," + centerY + "L " + targetX + "," + targetY }),
text));
}); });
var wrapEdge = (function (EdgeComponent) { var wrapEdge = (function (EdgeComponent) {
var EdgeWrapper = React.memo(function (_a) { var EdgeWrapper = React.memo(function (_a) {
var id = _a.id, source = _a.source, target = _a.target, type = _a.type, animated = _a.animated, selected = _a.selected, onClick = _a.onClick, isInteractive = _a.isInteractive, rest = __rest(_a, ["id", "source", "target", "type", "animated", "selected", "onClick", "isInteractive"]); var id = _a.id, source = _a.source, target = _a.target, type = _a.type, animated = _a.animated, selected = _a.selected, onClick = _a.onClick, isInteractive = _a.isInteractive, label = _a.label, labelStyle = _a.labelStyle, labelShowBg = _a.labelShowBg, labelBgStyle = _a.labelBgStyle, rest = __rest(_a, ["id", "source", "target", "type", "animated", "selected", "onClick", "isInteractive", "label", "labelStyle", "labelShowBg", "labelBgStyle"]);
var edgeClasses = classnames('react-flow__edge', { selected: selected, animated: animated }); var edgeClasses = classnames('react-flow__edge', { selected: selected, animated: animated });
var onEdgeClick = function () { var onEdgeClick = function () {
if (!isInteractive) { if (!isInteractive) {
@@ -9318,7 +9357,7 @@ var wrapEdge = (function (EdgeComponent) {
onClick({ id: id, source: source, target: target, type: type }); onClick({ id: id, source: source, target: target, type: type });
}; };
return (React__default.createElement("g", { className: edgeClasses, onClick: onEdgeClick }, return (React__default.createElement("g", { className: edgeClasses, onClick: onEdgeClick },
React__default.createElement(EdgeComponent, __assign({ id: id, source: source, target: target, type: type, animated: animated, selected: selected, onClick: onClick }, rest)))); React__default.createElement(EdgeComponent, __assign({ id: id, source: source, target: target, type: type, animated: animated, selected: selected, onClick: onClick, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle }, rest))));
}); });
EdgeWrapper.displayName = 'EdgeWrapper'; EdgeWrapper.displayName = 'EdgeWrapper';
return EdgeWrapper; return EdgeWrapper;
@@ -9366,7 +9405,7 @@ function styleInject(css, ref) {
} }
} }
var css_248z = ".react-flow {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.react-flow__renderer {\n width: 100%;\n height: 100%;\n position: absolute;\n}\n\n.react-flow__zoompane {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1;\n}\n\n.react-flow__selectionpane {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2;\n}\n\n.react-flow__selection {\n position: absolute;\n top: 0;\n left: 0;\n background: rgba(0, 89, 220, 0.08);\n border: 1px dotted rgba(0, 89, 220, 0.8);\n}\n\n.react-flow__edges {\n position: absolute;\n top: 0;\n left: 0;\n pointer-events: none;\n z-index: 2;\n}\n\n.react-flow__edge {\n fill: none;\n stroke: #bbb;\n stroke-width: 2;\n pointer-events: all;\n}\n\n.react-flow__edge.selected {\n stroke: #555;\n }\n\n.react-flow__edge.animated {\n stroke-dasharray: 5;\n -webkit-animation: dashdraw 0.5s linear infinite;\n animation: dashdraw 0.5s linear infinite;\n }\n\n.react-flow__edge.connection {\n stroke: '#ddd';\n pointer-events: none;\n }\n\n@-webkit-keyframes dashdraw {\n from {\n stroke-dashoffset: 10;\n }\n}\n\n@keyframes dashdraw {\n from {\n stroke-dashoffset: 10;\n }\n}\n\n.react-flow__nodes {\n width: 100%;\n height: 100%;\n position: absolute;\n z-index: 3;\n pointer-events: none;\n transform-origin: 0 0;\n}\n\n.is-interactive .react-flow__node {\n cursor: -webkit-grab;\n cursor: grab;\n }\n\n.is-interactive .react-flow__node:hover > * {\n box-shadow: 0 1px 5px 2px rgba(0, 0, 0, 0.08);\n }\n\n.is-interactive .react-flow__handle {\n cursor: crosshair;\n }\n\n.react-flow__node {\n position: absolute;\n color: #222;\n font-family: sans-serif;\n font-size: 12px;\n text-align: center;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n pointer-events: all;\n transform-origin: 0 0;\n}\n\n.react-flow__node.selected > * {\n box-shadow: 0 0 0 2px #555;\n }\n\n.react-flow__handle {\n position: absolute;\n width: 10px;\n height: 8px;\n background: rgba(255, 255, 255, 0.4);\n}\n\n.react-flow__handle.bottom {\n top: auto;\n left: 50%;\n bottom: 0;\n transform: translate(-50%, 0);\n }\n\n.react-flow__handle.top {\n left: 50%;\n top: 0;\n transform: translate(-50%, 0);\n }\n\n.react-flow__handle.left {\n top: 50%;\n left: 0;\n transform: translate(0, -50%);\n }\n\n.react-flow__handle.right {\n right: 0;\n top: 50%;\n transform: translate(0, -50%);\n }\n\n.react-flow__nodesselection {\n z-index: 3;\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n transform-origin: left top;\n pointer-events: none;\n}\n\n.react-flow__nodesselection-rect {\n position: absolute;\n background: rgba(0, 89, 220, 0.08);\n border: 1px dotted rgba(0, 89, 220, 0.8);\n pointer-events: all;\n }\n\n.react-flow__controls {\n box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.08);\n}\n\n.react-flow__controls-button {\n background: #fefefe;\n border-bottom: 1px solid #eee;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 16px;\n height: 16px;\n cursor: pointer;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n padding: 5px;\n }\n\n.react-flow__controls-button svg {\n width: 100%;\n }\n\n.react-flow__controls-button:hover {\n background: #f4f4f4;\n }\n"; var css_248z = ".react-flow {\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n}\n\n.react-flow__renderer {\n width: 100%;\n height: 100%;\n position: absolute;\n}\n\n.react-flow__zoompane {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1;\n}\n\n.react-flow__selectionpane {\n width: 100%;\n height: 100%;\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2;\n}\n\n.react-flow__selection {\n position: absolute;\n top: 0;\n left: 0;\n background: rgba(0, 89, 220, 0.08);\n border: 1px dotted rgba(0, 89, 220, 0.8);\n}\n\n.react-flow__edges {\n position: absolute;\n top: 0;\n left: 0;\n pointer-events: none;\n z-index: 2;\n}\n\n.react-flow__edge {\n pointer-events: all;\n}\n\n.react-flow__edge.animated path {\n stroke-dasharray: 5;\n -webkit-animation: dashdraw 0.5s linear infinite;\n animation: dashdraw 0.5s linear infinite;\n }\n\n.react-flow__edge.connection {\n stroke: '#ddd';\n pointer-events: none;\n }\n\n.react-flow__edge-path {\n fill: none;\n stroke: #bbb;\n stroke-width: 2;\n}\n\n.react-flow__edge-path.selected {\n stroke: #555;\n }\n\n.react-flow__edge-text {\n font-size: 12px;\n pointer-events: none;\n}\n\n.react-flow__edge-textbg {\n fill: white;\n}\n\n@-webkit-keyframes dashdraw {\n from {\n stroke-dashoffset: 10;\n }\n}\n\n@keyframes dashdraw {\n from {\n stroke-dashoffset: 10;\n }\n}\n\n.react-flow__nodes {\n width: 100%;\n height: 100%;\n position: absolute;\n z-index: 3;\n pointer-events: none;\n transform-origin: 0 0;\n}\n\n.is-interactive .react-flow__node {\n cursor: -webkit-grab;\n cursor: grab;\n }\n\n.is-interactive .react-flow__node:hover > * {\n box-shadow: 0 1px 5px 2px rgba(0, 0, 0, 0.08);\n }\n\n.is-interactive .react-flow__handle {\n cursor: crosshair;\n }\n\n.react-flow__node {\n position: absolute;\n color: #222;\n font-family: sans-serif;\n font-size: 12px;\n text-align: center;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n pointer-events: all;\n transform-origin: 0 0;\n}\n\n.react-flow__node.selected > * {\n box-shadow: 0 0 0 2px #555;\n }\n\n.react-flow__handle {\n position: absolute;\n width: 10px;\n height: 8px;\n background: rgba(255, 255, 255, 0.4);\n}\n\n.react-flow__handle.bottom {\n top: auto;\n left: 50%;\n bottom: 0;\n transform: translate(-50%, 0);\n }\n\n.react-flow__handle.top {\n left: 50%;\n top: 0;\n transform: translate(-50%, 0);\n }\n\n.react-flow__handle.left {\n top: 50%;\n left: 0;\n transform: translate(0, -50%);\n }\n\n.react-flow__handle.right {\n right: 0;\n top: 50%;\n transform: translate(0, -50%);\n }\n\n.react-flow__nodesselection {\n z-index: 3;\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n transform-origin: left top;\n pointer-events: none;\n}\n\n.react-flow__nodesselection-rect {\n position: absolute;\n background: rgba(0, 89, 220, 0.08);\n border: 1px dotted rgba(0, 89, 220, 0.8);\n pointer-events: all;\n }\n\n.react-flow__controls {\n box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.08);\n}\n\n.react-flow__controls-button {\n background: #fefefe;\n border-bottom: 1px solid #eee;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 16px;\n height: 16px;\n cursor: pointer;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n padding: 5px;\n }\n\n.react-flow__controls-button svg {\n width: 100%;\n }\n\n.react-flow__controls-button:hover {\n background: #f4f4f4;\n }\n";
styleInject(css_248z); styleInject(css_248z);
var ReactFlow = function (_a) { var ReactFlow = function (_a) {
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,4 +1,4 @@
import React from 'react'; import React from 'react';
import { EdgeBezierProps } from '../../types'; import { EdgeBezierProps } from '../../types';
declare const _default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, style, }: EdgeBezierProps) => JSX.Element>; declare const _default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, label, labelStyle, labelShowBg, labelBgStyle, style, }: EdgeBezierProps) => JSX.Element>;
export default _default; export default _default;
+4
View File
@@ -0,0 +1,4 @@
import React from 'react';
import { EdgeTextProps } from '../../types';
declare const _default: React.MemoExoticComponent<({ x, y, label, labelStyle, labelShowBg, labelBgStyle }: EdgeTextProps) => JSX.Element | null>;
export default _default;
+1 -1
View File
@@ -1,4 +1,4 @@
import React from 'react'; import React from 'react';
import { EdgeProps } from '../../types'; import { EdgeProps } from '../../types';
declare const _default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, style }: EdgeProps) => JSX.Element>; declare const _default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, style }: EdgeProps) => JSX.Element>;
export default _default; export default _default;
+1 -1
View File
@@ -1,4 +1,4 @@
import React from 'react'; import React from 'react';
import { EdgeProps } from '../../types'; import { EdgeProps } from '../../types';
declare const _default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, style }: EdgeProps) => JSX.Element>; declare const _default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, style }: EdgeProps) => JSX.Element>;
export default _default; export default _default;
+6 -2
View File
@@ -1,14 +1,18 @@
import React from 'react'; import React, { CSSProperties } from 'react';
import { ElementId, Edge, EdgeCompProps } from '../../types'; import { ElementId, Edge, EdgeCompProps } from '../../types';
interface EdgeWrapperProps { interface EdgeWrapperProps {
id: ElementId; id: ElementId;
source: ElementId; source: ElementId;
target: ElementId; target: ElementId;
type: any; type: any;
label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle: CSSProperties;
onClick: (edge: Edge) => void; onClick: (edge: Edge) => void;
animated: boolean; animated: boolean;
selected: boolean; selected: boolean;
isInteractive: boolean; isInteractive: boolean;
} }
declare const _default: (EdgeComponent: React.ComponentType<EdgeCompProps>) => React.MemoExoticComponent<({ id, source, target, type, animated, selected, onClick, isInteractive, ...rest }: EdgeWrapperProps) => JSX.Element>; declare const _default: (EdgeComponent: React.ComponentType<EdgeCompProps>) => React.MemoExoticComponent<({ id, source, target, type, animated, selected, onClick, isInteractive, label, labelStyle, labelShowBg, labelBgStyle, ...rest }: EdgeWrapperProps) => JSX.Element>;
export default _default; export default _default;
+3 -3
View File
@@ -40,9 +40,9 @@ declare const ReactFlow: {
output: ({ data, style, targetPosition }: import("../../types").NodeProps) => JSX.Element; output: ({ data, style, targetPosition }: import("../../types").NodeProps) => JSX.Element;
}; };
edgeTypes: { edgeTypes: {
default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, style, }: import("../../types").EdgeBezierProps) => JSX.Element>; default: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, label, labelStyle, labelShowBg, labelBgStyle, style, }: import("../../types").EdgeBezierProps) => JSX.Element>;
straight: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, style }: import("../../types").EdgeProps) => JSX.Element>; straight: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, style }: import("../../types").EdgeProps) => JSX.Element>;
step: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, style }: import("../../types").EdgeProps) => JSX.Element>; step: React.MemoExoticComponent<({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, style }: import("../../types").EdgeProps) => JSX.Element>;
}; };
connectionLineType: string; connectionLineType: string;
connectionLineStyle: {}; connectionLineStyle: {};
+23 -3
View File
@@ -1,4 +1,4 @@
import { CSSProperties, SVGAttributes } from 'react'; import { CSSProperties } from 'react';
export declare type ElementId = string; export declare type ElementId = string;
export declare type Elements = Array<Node | Edge>; export declare type Elements = Array<Node | Edge>;
export declare type Transform = [number, number, number]; export declare type Transform = [number, number, number];
@@ -51,7 +51,11 @@ export interface Edge {
type?: string; type?: string;
source: ElementId; source: ElementId;
target: ElementId; target: ElementId;
style?: SVGAttributes<{}>; label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
style?: CSSProperties;
animated?: boolean; animated?: boolean;
} }
export interface EdgeProps { export interface EdgeProps {
@@ -59,7 +63,11 @@ export interface EdgeProps {
sourceY: number; sourceY: number;
targetX: number; targetX: number;
targetY: number; targetY: number;
style?: SVGAttributes<{}>; label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
style?: CSSProperties;
} }
export interface EdgeBezierProps extends EdgeProps { export interface EdgeBezierProps extends EdgeProps {
sourcePosition: Position; sourcePosition: Position;
@@ -127,8 +135,20 @@ export interface EdgeCompProps {
source: ElementId; source: ElementId;
target: ElementId; target: ElementId;
type: any; type: any;
label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
onClick?: (edge: Edge) => void; onClick?: (edge: Edge) => void;
animated?: boolean; animated?: boolean;
selected?: boolean; selected?: boolean;
} }
export interface EdgeTextProps {
x: number;
y: number;
label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
}
export {}; export {};
+1 -1
View File
@@ -11,7 +11,7 @@ const initialElements = [
{ id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } }, { id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } },
{ id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } }, { id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } }, { id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } },
{ id: 'e1-2', source: '1', target: '2', animated: true }, { id: 'e1-2', source: '1', target: '2', animated: true, label: 'edge text' },
{ id: 'e1-3', source: '1', target: '3' }, { id: 'e1-3', source: '1', target: '3' },
]; ];
+51
View File
@@ -0,0 +1,51 @@
import React, { useState } from 'react';
import ReactFlow, { removeElements, addEdge, MiniMap, Controls } from 'react-flow-renderer';
const onNodeDragStop = node => console.log('drag stop', node);
const onElementClick = element => console.log('click', element);
const onLoad = (graph) => {
graph.fitView();
};
const initialElements = [
{ id: '1', type: 'input', data: { label: 'Input Node 1' }, position: { x: 250, y: 0 } },
{ id: '2', data: { label: 'Node 2' }, position: { x: 150, y: 100 } },
{ id: '3', data: { label: 'Node 3' }, position: { x: 250, y: 200 } },
{ id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 300 } },
{ id: '5', data: { label: 'Node 5' }, position: { x: 450, y: 400 } },
{ id: '6', type: 'output', data: { label: 'Output Node 5' }, position: { x: 250, y: 550 } },
{ id: '7', type: 'output', data: { label: 'Output Node 6' }, position: { x: 550, y: 550 } },
{ id: 'e1-2', source: '1', target: '2', label: 'bezier edge', labelBgStyle: { fillOpacity: 0.75 } },
{ id: 'e2-3', source: '2', target: '3', type: 'step', label: 'step edge' },
{ id: 'e3-4', source: '3', target: '4', type: 'straight', label: 'straight edge' },
{ id: 'e3-5', source: '4', target: '5', animated: true, label: 'animated styled edge', style: { stroke: 'red' } },
{ id: 'e5-6', source: '5', target: '6', label: 'styled label', labelStyle: { fill: 'red', fontWeight: 700 } },
{ id: 'e5-7', source: '5', target: '7', label: 'label with styled bg', labelBgStyle: { fill: '#eee', fillOpacity: 0.7 } },
]
const EdgesFlow = () => {
const [elements, setElements] = useState(initialElements);
const onElementsRemove = (elementsToRemove) => setElements(els => removeElements(elementsToRemove, els));
const onConnect = (params) => setElements(els => addEdge(params, els));
return (
<ReactFlow
elements={elements}
onElementClick={onElementClick}
onElementsRemove={onElementsRemove}
onConnect={onConnect}
onNodeDragStop={onNodeDragStop}
style={{ width: '100%', height: '100%' }}
onLoad={onLoad}
snapToGrid={true}
>
<MiniMap />
<Controls />
</ReactFlow>
);
}
export default EdgesFlow;
+3 -3
View File
@@ -18,13 +18,13 @@ const initialElements = [
sourcePosition: 'right' sourcePosition: 'right'
}, },
{ id: '4', data: { label: 'Node 4' }, position: { x: 500, y: 200 }, targetPosition: 'left' }, { id: '4', data: { label: 'Node 4' }, position: { x: 500, y: 200 }, targetPosition: 'left' },
{ id: '5', type: 'output', data: { label: 'Output Node 5'}, position: { x: 300, y: 300 } }, { id: '5', type: 'output', data: { label: 'Output Node 5' }, position: { x: 300, y: 300 } },
{ id: '6', type: 'output', data: { label: 'Output Node 6' }, position: { x: 600, y: 400 } }, { id: '6', type: 'output', data: { label: 'Output Node 6' }, position: { x: 600, y: 400 } },
{ id: 'e1-2', source: '1', target: '2', animated: true }, { id: 'e1-2', source: '1', target: '2', animated: true, label: 'edge text', labelBgStyle: { fillOpacity: 0.75 } },
{ id: 'e2-3', source: '2', target: '3', animated: true }, { id: 'e2-3', source: '2', target: '3', animated: true },
{ id: 'e3-4', source: '3', target: '4', animated: true }, { id: 'e3-4', source: '3', target: '4', animated: true },
{ id: 'e3-5', source: '4', target: '5', animated: true, type: 'step' }, { id: 'e3-5', source: '4', target: '5', animated: true, type: 'step' },
{ id: 'e5-6b', source: '4', target: '6', type: 'step' }, { id: 'e5-6b', source: '4', target: '6', type: 'step', label: 'styled label', labelStyle: { fill: 'red', fontWeight: 700 } },
] ]
const RichGraph = () => { const RichGraph = () => {
+6 -1
View File
@@ -8,6 +8,7 @@ import CustomNode from './CustomNode';
import Stress from './Stress'; import Stress from './Stress';
import Inactive from './Inactive'; import Inactive from './Inactive';
import Empty from './Empty'; import Empty from './Empty';
import Edges from './Edges';
import './index.css'; import './index.css';
@@ -27,10 +28,14 @@ const routes = [{
path: '/stress', path: '/stress',
component: Stress, component: Stress,
label: 'Stress' label: 'Stress'
}, {
path: '/edges',
component: Edges,
label: 'Edges'
}, { }, {
path: '/empty', path: '/empty',
component: Empty component: Empty
},{ }, {
path: '/inactive', path: '/inactive',
component: Inactive component: Inactive
}]; }];
+25 -4
View File
@@ -1,5 +1,6 @@
import React, { memo } from 'react'; import React, { memo } from 'react';
import EdgeText from './EdgeText';
import { EdgeBezierProps, Position } from '../../types'; import { EdgeBezierProps, Position } from '../../types';
export default memo( export default memo(
@@ -10,23 +11,43 @@ export default memo(
targetY, targetY,
sourcePosition = Position.Bottom, sourcePosition = Position.Bottom,
targetPosition = Position.Top, targetPosition = Position.Top,
label,
labelStyle,
labelShowBg,
labelBgStyle,
style = {}, style = {},
}: EdgeBezierProps) => { }: EdgeBezierProps) => {
const yOffset = Math.abs(targetY - sourceY) / 2; const yOffset = Math.abs(targetY - sourceY) / 2;
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset; const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
const xOffset = Math.abs(targetX - sourceX) / 2;
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
let dAttr = `M${sourceX},${sourceY} C${sourceX},${centerY} ${targetX},${centerY} ${targetX},${targetY}`; let dAttr = `M${sourceX},${sourceY} C${sourceX},${centerY} ${targetX},${centerY} ${targetX},${targetY}`;
const leftAndRight = [Position.Left, Position.Right]; const leftAndRight = [Position.Left, Position.Right];
if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) { if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
const xOffset = Math.abs(targetX - sourceX) / 2;
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
dAttr = `M${sourceX},${sourceY} C${centerX},${sourceY} ${centerX},${targetY} ${targetX},${targetY}`; dAttr = `M${sourceX},${sourceY} C${centerX},${sourceY} ${centerX},${targetY} ${targetX},${targetY}`;
} else if (leftAndRight.includes(sourcePosition) || leftAndRight.includes(targetPosition)) { } else if (leftAndRight.includes(sourcePosition) || leftAndRight.includes(targetPosition)) {
dAttr = `M${sourceX},${sourceY} C${sourceX},${targetY} ${sourceX},${targetY} ${targetX},${targetY}`; dAttr = `M${sourceX},${sourceY} C${sourceX},${targetY} ${sourceX},${targetY} ${targetX},${targetY}`;
} }
return <path {...style} d={dAttr} />; const text = label ? (
<EdgeText
x={centerX}
y={centerY}
label={label}
labelStyle={labelStyle}
labelShowBg={labelShowBg}
labelBgStyle={labelBgStyle}
/>
) : null;
return (
<g>
<path style={style} d={dAttr} className="react-flow__edge-path" />
{text}
</g>
);
} }
); );
+44
View File
@@ -0,0 +1,44 @@
import React, { memo, useRef, useState, useEffect } from 'react';
import { EdgeTextProps, Rect } from '../../types';
const textBgPadding = 2;
export default memo(({ x, y, label, labelStyle = {}, labelShowBg = true, labelBgStyle = {} }: EdgeTextProps) => {
const edgeRef = useRef<SVGTextElement>(null);
const [edgeTextBbox, setEdgeTextBbox] = useState<Rect>({ x: 0, y: 0, width: 0, height: 0 });
useEffect(() => {
if (edgeRef.current) {
const textBbox = edgeRef.current.getBBox();
setEdgeTextBbox({
x: textBbox.x,
y: textBbox.y,
width: textBbox.width,
height: textBbox.height,
});
}
}, []);
if (typeof label === 'undefined' || !label) {
return null;
}
return (
<g transform={`translate(${x - edgeTextBbox.width / 2} ${y - edgeTextBbox.height / 2})`}>
{labelShowBg && (
<rect
width={edgeTextBbox.width + 2 * textBgPadding}
x={-textBgPadding}
y={-textBgPadding}
height={edgeTextBbox.height + 2 * textBgPadding}
className="react-flow__edge-textbg"
style={labelBgStyle}
/>
)}
<text className="react-flow__edge-text" y={edgeTextBbox.height / 2} dy="0.3em" ref={edgeRef} style={labelStyle}>
{label}
</text>
</g>
);
});
+24 -5
View File
@@ -1,17 +1,36 @@
import React, { memo } from 'react'; import React, { memo } from 'react';
import EdgeText from './EdgeText';
import { EdgeProps } from '../../types'; import { EdgeProps } from '../../types';
export default memo( export default memo(
({ sourceX, sourceY, targetX, targetY, style = {} }: EdgeProps) => { ({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, style = {} }: EdgeProps) => {
const yOffset = Math.abs(targetY - sourceY) / 2; const yOffset = Math.abs(targetY - sourceY) / 2;
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset; const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
return ( const xOffset = Math.abs(targetX - sourceX) / 2;
<path const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
{...style}
d={`M ${sourceX},${sourceY}L ${sourceX},${centerY}L ${targetX},${centerY}L ${targetX},${targetY}`} const text = label ? (
<EdgeText
x={centerX}
y={centerY}
label={label}
labelStyle={labelStyle}
labelShowBg={labelShowBg}
labelBgStyle={labelBgStyle}
/> />
) : null;
return (
<g>
<path
style={style}
className="react-flow__edge-path"
d={`M ${sourceX},${sourceY}L ${sourceX},${centerY}L ${targetX},${centerY}L ${targetX},${targetY}`}
/>
{text}
</g>
); );
} }
); );
+23 -2
View File
@@ -1,11 +1,32 @@
import React, { memo } from 'react'; import React, { memo } from 'react';
import EdgeText from './EdgeText';
import { EdgeProps } from '../../types'; import { EdgeProps } from '../../types';
export default memo( export default memo(
({ sourceX, sourceY, targetX, targetY, style = {} }: EdgeProps) => { ({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, style = {} }: EdgeProps) => {
const yOffset = Math.abs(targetY - sourceY) / 2;
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
const xOffset = Math.abs(targetX - sourceX) / 2;
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
const text = label ? (
<EdgeText
x={centerX}
y={centerY}
label={label}
labelStyle={labelStyle}
labelShowBg={labelShowBg}
labelBgStyle={labelBgStyle}
/>
) : null;
return ( return (
<path {...style} d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`} /> <g>
<path style={style} className="react-flow__edge-path" d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`} />
{text}
</g>
); );
} }
); );
+24 -2
View File
@@ -1,4 +1,4 @@
import React, { memo, ComponentType } from 'react'; import React, { memo, ComponentType, CSSProperties } from 'react';
import cx from 'classnames'; import cx from 'classnames';
import store from '../../store'; import store from '../../store';
@@ -9,6 +9,10 @@ interface EdgeWrapperProps {
source: ElementId; source: ElementId;
target: ElementId; target: ElementId;
type: any; type: any;
label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle: CSSProperties;
onClick: (edge: Edge) => void; onClick: (edge: Edge) => void;
animated: boolean; animated: boolean;
selected: boolean; selected: boolean;
@@ -17,7 +21,21 @@ interface EdgeWrapperProps {
export default (EdgeComponent: ComponentType<EdgeCompProps>) => { export default (EdgeComponent: ComponentType<EdgeCompProps>) => {
const EdgeWrapper = memo( const EdgeWrapper = memo(
({ id, source, target, type, animated, selected, onClick, isInteractive, ...rest }: EdgeWrapperProps) => { ({
id,
source,
target,
type,
animated,
selected,
onClick,
isInteractive,
label,
labelStyle,
labelShowBg,
labelBgStyle,
...rest
}: EdgeWrapperProps) => {
const edgeClasses = cx('react-flow__edge', { selected, animated }); const edgeClasses = cx('react-flow__edge', { selected, animated });
const onEdgeClick = (): void => { const onEdgeClick = (): void => {
if (!isInteractive) { if (!isInteractive) {
@@ -38,6 +56,10 @@ export default (EdgeComponent: ComponentType<EdgeCompProps>) => {
animated={animated} animated={animated}
selected={selected} selected={selected}
onClick={onClick} onClick={onClick}
label={label}
labelStyle={labelStyle}
labelShowBg={labelShowBg}
labelBgStyle={labelBgStyle}
{...rest} {...rest}
/> />
</g> </g>
+9 -5
View File
@@ -83,7 +83,7 @@ function getHandle(bounds: HandleElement[], handleId: ElementId | null): HandleE
if (bounds.length === 1 || !handleId) { if (bounds.length === 1 || !handleId) {
handle = bounds[0]; handle = bounds[0];
} else if (handleId) { } else if (handleId) {
handle = bounds.find(d => d.id === handleId); handle = bounds.find((d) => d.id === handleId);
} }
return handle; return handle;
@@ -123,8 +123,8 @@ function renderEdge(
const [sourceId, sourceHandleId] = edge.source.split('__'); const [sourceId, sourceHandleId] = edge.source.split('__');
const [targetId, targetHandleId] = edge.target.split('__'); const [targetId, targetHandleId] = edge.target.split('__');
const sourceNode = nodes.find(n => n.id === sourceId); const sourceNode = nodes.find((n) => n.id === sourceId);
const targetNode = nodes.find(n => n.id === targetId); const targetNode = nodes.find((n) => n.id === targetId);
if (!sourceNode) { if (!sourceNode) {
throw new Error(`couldn't create edge for source id: ${sourceId}`); throw new Error(`couldn't create edge for source id: ${sourceId}`);
@@ -155,7 +155,7 @@ function renderEdge(
); );
const isSelected = (selectedElements as Edge[]).some( const isSelected = (selectedElements as Edge[]).some(
elm => isEdge(elm) && elm.source === sourceId && elm.target === targetId (elm) => isEdge(elm) && elm.source === sourceId && elm.target === targetId
); );
return ( return (
@@ -166,6 +166,10 @@ function renderEdge(
onClick={props.onElementClick} onClick={props.onElementClick}
selected={isSelected} selected={isSelected}
animated={edge.animated} animated={edge.animated}
label={edge.label}
labelStyle={edge.labelStyle}
labelShowBg={edge.labelShowBg}
labelBgStyle={edge.labelBgStyle}
style={edge.style} style={edge.style}
source={sourceId} source={sourceId}
target={targetId} target={targetId}
@@ -191,7 +195,7 @@ const EdgeRenderer = memo((props: EdgeRendererProps) => {
connectionPosition: { x, y }, connectionPosition: { x, y },
selectedElements, selectedElements,
isInteractive, isInteractive,
} = useStoreState(s => ({ } = useStoreState((s) => ({
transform: s.transform, transform: s.transform,
edges: s.edges, edges: s.edges,
nodes: s.nodes, nodes: s.nodes,
+20 -8
View File
@@ -46,16 +46,9 @@
} }
.react-flow__edge { .react-flow__edge {
fill: none;
stroke: #bbb;
stroke-width: 2;
pointer-events: all; pointer-events: all;
&.selected { &.animated path {
stroke: #555;
}
&.animated {
stroke-dasharray: 5; stroke-dasharray: 5;
animation: dashdraw 0.5s linear infinite; animation: dashdraw 0.5s linear infinite;
} }
@@ -66,6 +59,25 @@
} }
} }
.react-flow__edge-path {
fill: none;
stroke: #bbb;
stroke-width: 2;
&.selected {
stroke: #555;
}
}
.react-flow__edge-text {
font-size: 12px;
pointer-events: none;
}
.react-flow__edge-textbg {
fill: white;
}
@keyframes dashdraw { @keyframes dashdraw {
from { from {
stroke-dashoffset: 10; stroke-dashoffset: 10;
+24 -3
View File
@@ -1,4 +1,4 @@
import { CSSProperties, SVGAttributes } from 'react'; import { CSSProperties } from 'react';
export type ElementId = string; export type ElementId = string;
@@ -63,7 +63,11 @@ export interface Edge {
type?: string; type?: string;
source: ElementId; source: ElementId;
target: ElementId; target: ElementId;
style?: SVGAttributes<{}>; label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
style?: CSSProperties;
animated?: boolean; animated?: boolean;
} }
@@ -72,7 +76,11 @@ export interface EdgeProps {
sourceY: number; sourceY: number;
targetX: number; targetX: number;
targetY: number; targetY: number;
style?: SVGAttributes<{}>; label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
style?: CSSProperties;
} }
export interface EdgeBezierProps extends EdgeProps { export interface EdgeBezierProps extends EdgeProps {
@@ -151,7 +159,20 @@ export interface EdgeCompProps {
source: ElementId; source: ElementId;
target: ElementId; target: ElementId;
type: any; type: any;
label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
onClick?: (edge: Edge) => void; onClick?: (edge: Edge) => void;
animated?: boolean; animated?: boolean;
selected?: boolean; selected?: boolean;
} }
export interface EdgeTextProps {
x: number;
y: number;
label?: string;
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle?: CSSProperties;
}