react-network-diagrams
Version:
504 lines (433 loc) • 24.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Connection = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
var _propTypes = require("prop-types");
var _propTypes2 = _interopRequireDefault(_propTypes);
var _Endpoint = require("./Endpoint");
var _SimpleEdge = require("./SimpleEdge");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Copyright (c) 2018, The Regents of the University of California,
* through Lawrence Berkeley National Laboratory (subject to receipt
* of any required approvals from the U.S. Dept. of Energy).
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* The `x1`, `x2`, `y1`, and `y2` properties determine the position of the endpoints on the `<svg>` element.
* A path is then drawn betwween the endpoints. If the lineShape property is set to "square",
* the width of the square will be the distance between x1 and x2, with the height of the square
* determined by the size prop.
*
* The `labelPosition`, determines where the label will be positioned around the line. The `xOffset` and
* `yOffset` properties allow you to customize the distance the label is from the `x` and `y` properties.
*
* The `label` property is the name that will be displayed on the line. If you want to display multiple
* lines, the label can take an array of strings, with each array element displayed on a separate line.
*/
var Connection = exports.Connection = function (_React$Component) {
_inherits(Connection, _React$Component);
function Connection(props) {
_classCallCheck(this, Connection);
var _this = _possibleConstructorReturn(this, (Connection.__proto__ || Object.getPrototypeOf(Connection)).call(this, props));
_this.state = {
highlighted: false
};
_this.handleMouseOut = _this.handleMouseOut.bind(_this);
_this.handleMouseOver = _this.handleMouseOver.bind(_this);
_this.handleSelectionChanged = _this.handleSelectionChanged.bind(_this);
return _this;
}
/**
* User hovers over the circuit
*/
_createClass(Connection, [{
key: "handleMouseOver",
value: function handleMouseOver() {
if (!this.props.noNavigate) {
this.setState({ highlighted: true });
}
}
/**
* Use stops hovering over circuit
*/
}, {
key: "handleMouseOut",
value: function handleMouseOut() {
if (!this.props.noNavigate) {
this.setState({ highlighted: false });
}
}
}, {
key: "handleSelectionChanged",
value: function handleSelectionChanged(e, value) {
if (!this.props.noNavigate) {
this.props.onSelectionChange(e, value);
}
}
}, {
key: "renderEndpoints",
value: function renderEndpoints() {
if (this.props.arrow) {
return _react2.default.createElement("g", null);
} else {
return _react2.default.createElement(
"g",
null,
_react2.default.createElement(_Endpoint.Endpoint, {
x: this.props.x1,
y: this.props.y1,
key: "line-begin",
style: this.props.style,
radius: this.props.radius,
shape: this.props.endpointShape,
roundedX: this.props.endPointRoundedX,
roundedY: this.props.endPointRoundedY,
highlighted: this.state.highlighted,
muted: this.props.muted,
selected: this.props.selected
}),
_react2.default.createElement(_Endpoint.Endpoint, {
x: this.props.x2,
y: this.props.y2,
key: "line-end",
style: this.props.style,
radius: this.props.radius,
shape: this.props.endpointShape,
roundedX: this.props.endPointRoundedX,
roundedY: this.props.endPointRoundedY,
highlighted: this.state.highlighted,
muted: this.props.muted,
selected: this.props.selected
})
);
}
}
}, {
key: "render",
value: function render() {
var xOffset = void 0;
var yOffset = void 0;
if (this.props.labelOffsetX === undefined) {
xOffset = this.props.radius * 1.33;
} else {
xOffset = this.props.labelOffsetX;
}
if (this.props.labelOffsetY === undefined) {
yOffset = this.props.radius * 1.33;
} else {
yOffset = this.props.labelOffsetY;
}
var hitStyle = {
cursor: this.props.noNavigate ? "default" : "pointer",
stroke: "#FFF",
strokeWidth: 8
};
var navTo = this.props.navTo;
var width = void 0;
var stroke = void 0;
var fill = void 0;
var offset = void 0;
if (this.props.lineShape === "angled") {
offset = this.props.bendOffset;
} else {
offset = this.props.curveOffset;
}
if (this.state.highlighted) {
width = this.props.style.line.highlighted.strokeWidth;
stroke = this.props.style.line.highlighted.stroke;
fill = this.props.style.line.highlighted.fill;
} else {
width = this.props.style.line.normal.strokeWidth;
stroke = this.props.style.line.normal.stroke;
fill = this.props.style.line.normal.fill;
}
return _react2.default.createElement(
"g",
null,
_react2.default.createElement(
"g",
null,
_react2.default.createElement(_SimpleEdge.SimpleEdge
// Positional Props used by all shapes
, {
x1: this.props.x1,
x2: this.props.x2,
y1: this.props.y1,
y2: this.props.y2,
shape: this.props.lineShape,
key: "line-path",
label: this.props.label,
labelPosition: this.props.labelPosition,
labelStyle: this.props.style.label,
labelOffsetX: xOffset,
labelOffsetY: yOffset,
textAnchor: this.props.textAnchor,
color: stroke,
width: width,
muted: this.props.muted,
selected: this.props.selected,
classed: this.props.classed,
roundedX: this.props.roundedX,
roundedY: this.props.roundedY,
fillColor: fill,
size: this.props.size,
centerLine: this.props.centerLine,
arrow: this.props.arrow,
arrowWidth: this.props.arrowWidth,
arrowHeight: this.props.arrowHeight,
position: this.props.position,
offset: offset,
curveDirection: this.props.curveDirection,
name: navTo
})
),
_react2.default.createElement(
"g",
{ onMouseOver: this.handleMouseOver, onMouseOut: this.handleMouseOut },
_react2.default.createElement(_SimpleEdge.SimpleEdge, { x1: this.props.x1,
x2: this.props.x2,
y1: this.props.y1,
y2: this.props.y2
// Identity Props used by all shapes
, shape: this.props.lineShape // controls shape of the line
, key: "line-path-hit" // needed for react element
// Label Props used by all shapes
, label: this.props.label // provides label to be displayed
, labelPosition: this.props.labelPosition // controls where label
// is situated around the line
, labelStyle: this.props.style.label // controls the
// style of the label
, labelOffsetX: xOffset // controls the +/- x offset from labelPosition
, labelOffsetY: yOffset // controls the +/- y offset from labelPosition
, textAnchor: this.props.textAnchor // controls the positioning of the text
// Style Props
, color: hitStyle.stroke // controls color of the line
, width: hitStyle.strokeWidth // controls the stroke thickness
, muted: this.props.muted // controls style
, selected: this.props.selected // controls style
, classed: this.props.classed // provides a psuedo css class for the line
// Square props
, roundedX: this.props.roundedX // controls corner rounding
, roundedY: this.props.roundedY // controls corner rounding
, fillColor: fill // controls color of the fill
, size: this.props.size // controls height of square
, centerLine: this.props.centerLine // controls display of horizontal center line
// Arrow props, not used by square
, arrow: this.props.arrow // determines whether to
// display nodes or arrows at ends of line
, arrowWidth: this.props.arrowWidth // controls width of arrow
, arrowHeight: this.props.arrowHeight // controls height of arrow
// Line offset props, used by angle and arc
, position: this.props.position // controls angle of offset
, offset: offset // controls length of offset line
, curveDirection: this.props.curveDirection // controls left / right
// line path with reference
// to line center
// Navigation props
, name: navTo // returned value for _onSelection change - all
, onSelectionChange: this.handleSelectionChanged // callback function to
// control what happens if the
// element is clicked
, invisible: true // Internal prop for hiding this line
})
),
_react2.default.createElement(
"g",
null,
this.renderEndpoints()
)
);
}
}]);
return Connection;
}(_react2.default.Component);
Connection.propTypes = {
/**
* Controls shape of the line, can be "linear", "square", "angled", "arc".
*/
lineShape: _propTypes2.default.oneOf(["linear", "square", "angled", "arc"]),
//
// Positional Props used by all shapes
//
/** Controls the x-coordinate of the line beginning. */
x1: _propTypes2.default.number,
/** Controls the x-coordinate of the line end. */
x2: _propTypes2.default.number,
/** Controls the y-coordinate of the line beginning. */
y1: _propTypes2.default.number,
/** Controls the y-coordinate of the line end. */
y2: _propTypes2.default.number,
//
// Label Props used by all shapes
//
/**
* Provides label to be displayed; Takes either a string, or an array of
* strings for multi-line labels.
*/
label: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.arrayOf(_propTypes2.default.string)]),
/**
* Controls where label is situated around the line.
*/
labelPosition: _propTypes2.default.oneOf(["top", "bottom", "center"]),
/**
* Controls the x pixel offset from labelPosition
*/
labelOffsetX: _propTypes2.default.number,
/**
* Controls the y pixel offset from labelPosition
*/
labelOffsetY: _propTypes2.default.number,
/**
* Controls the justification of the text label
*/
textAnchor: _propTypes2.default.oneOf(["begin", "middle", "end"]),
//
// Style Props, used by all shapes
//
/**
* Object prop that controls the inline style for the react element.
*
* The style has three components, one for the two Line-caps (`node`),
* one for the label (`label`) and one for the line (`line`). Each group
* has up to four different possible options depending on the way the
* line and endpoint should be rendered:
* * `normal` - provides the standard view of the component
* * `selected` - for when the component is clicked
* * `muted` - for when the component is in the background
* * `highlighted` - is used when the component is hovered over
*
* The muted and selected props are boolean values that tell the lower
* level primitive that you want to use these styles. They will default
* to false unless specified. The `fill` css style on each category is used
* for line-caps and square connections, allowing different colors to be
* specified for the interior of the shapes.
*/
style: _propTypes2.default.object,
/** Display the endpoint muted */
muted: _propTypes2.default.bool,
/** Display the endpoint selected */
selected: _propTypes2.default.bool,
//
// Props for "square" shape
//
/** When the endpoint shape is a `square`, this controls the radius of corners. */
roundedX: _propTypes2.default.number,
/** When the endpoint shape is a `square`, this controls the radius of corners. */
roundedY: _propTypes2.default.number,
/**
* Used to determine the height of the square if the endpoint shape is a `square`,
* as well as when calculating the label position around a square.
*/
size: _propTypes2.default.number,
/** Boolean value that controls if a horizontal line is drawn down the center of a square. */
centerLine: _propTypes2.default.bool,
//
// Line offset Props, used by "angle" and "curved" shapes
//
/**
* Controls the angle of the offset from the center of the line.
*/
position: _propTypes2.default.number,
/**
* Controls the distance from the center x axis the curve will arc through
*/
curveOffset: _propTypes2.default.number,
/**
* Controls the length of the offset line
*/
bendOffset: _propTypes2.default.number,
/**
* The curveDirection property determines whether the curve moves to the
* left or the right of the non-horizontal vector between x1,y1 and x2,y2.
* The curveOffset property specifies the distance of the curve from the vector
* between x1, y1 and x2, y2. When position is specified, this will offset a linear,
* or curved line from the x1, y1, x2, y2 corrdinates using a combination of
* vectors.
*
* This functions slightly differently for angled connections and
* will instead rotate a point offset from the x and y by an angle. If the
* curveDirection is left, this will move clockwise, and will move counterClockwise if right.
*/
curveDirection: _propTypes2.default.oneOf(["left", "right"]),
//
// Linecap props, used by all shapes
//
/**
* Controls the size of the Line-cap
*/
radius: _propTypes2.default.number,
/**
* Controls the shape of the line-cap.
*/
endpointShape: _propTypes2.default.oneOf(["circle", "square", "cloud"]),
/**
* If a square endpoint shape is used, controls the corner rounding of the x-axis of the square
*/
endPointRoundedX: _propTypes2.default.number,
/**
* If a square endpoint shape is used, controls the corner rounding of the y-axis of the square
*/
endPointRoundedY: _propTypes2.default.number,
//
// Arrow props, not used by "square"
//
/**
* Boolean value that controls if a directional arrow is drawn instead of line-caps.
* When arrow is set to "true", the vector between x1, y1 and x2, y2 will have the
* Line-caps replaced with a directional arrow. Arrowheads can be sized using the
* arrowWidth and arrowHeight property.
*/
arrow: _propTypes2.default.bool,
/**
* Controls the width of an arrow head
*/
arrowWidth: _propTypes2.default.number,
/**
* Controls the height of an arrow head
*/
arrowHeight: _propTypes2.default.number,
//
// Navigation Props, used by all shapes
//
/**
* Boolean value that determines if the element uses the onSelectionChange change and can be clicked
*/
noNavigate: _propTypes2.default.bool,
/**
* Callback specified to handle selection of the circuit. The value supplied
* to the callback is whatever was specified in the navTo prop.
*/
onSelectionChange: _propTypes2.default.func,
/**
* Value passed down to the click handler at the lowest level primitive.
* Will return to the onSelectionChange its value.
*/
navTo: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number])
};
Connection.defaultProps = {
noNavigate: false,
labelPosition: "top",
radius: 2,
endpointShape: "circle",
classed: "circuit",
lineShape: "linear",
selected: false,
muted: false,
position: 0,
arrow: false,
arrowWidth: 10,
arrowHeight: 10,
curveDirection: "right",
curveOffset: 20,
size: 40
};