react-d3-graph
Advanced tools
Comparing version 2.2.0 to 2.3.0
# Change Log | ||
## [2.3.0](https://github.com/danielcaldas/react-d3-graph/tree/2.3.0) | ||
[Full Changelog](https://github.com/danielcaldas/react-d3-graph/compare/2.2.0...2.3.0) | ||
**Merged pull requests:** | ||
- Misc refactor improvements [\#231](https://github.com/danielcaldas/react-d3-graph/pull/231) ([danielcaldas](https://github.com/danielcaldas)) | ||
- onNodePositionChange [\#228](https://github.com/danielcaldas/react-d3-graph/pull/228) ([danielcaldas](https://github.com/danielcaldas)) | ||
- Upgrade to babel7 [\#225](https://github.com/danielcaldas/react-d3-graph/pull/225) ([danielcaldas](https://github.com/danielcaldas)) | ||
## [2.2.0](https://github.com/danielcaldas/react-d3-graph/tree/2.2.0) | ||
@@ -4,0 +14,0 @@ |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.computeNodeDegree = computeNodeDegree; | ||
exports.getTargetLeafConnections = getTargetLeafConnections; | ||
exports.isNodeVisible = isNodeVisible; | ||
exports.toggleLinksConnections = toggleLinksConnections; | ||
exports.toggleLinksMatrixConnections = toggleLinksMatrixConnections; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _graph = require("./graph.helper"); | ||
/** | ||
* @module Graph/collapse-helper | ||
* @description | ||
* Offers a series of methods that allow graph to perform the necessary operations to | ||
* create the collapsible behavior. | ||
* | ||
* Developer notes - collapsing nodes and maintaining state on links matrix. | ||
* | ||
* User interaction flow (for a collapsible graph) | ||
* 1. User clicks node | ||
* 2. All leaf connections of that node are not rendered anymore | ||
* 3. User clicks on same node | ||
* 4. All leaf connections of that node are rendered | ||
* | ||
* Internal react-d3-graph flow | ||
* 1. User clicks node | ||
* 2. Compute leaf connections for clicked node (rootNode, root as in 'root' of the event) | ||
* 3. Update connections matrix (based on 2.) | ||
* 4. Update d3Links array with toggled connections (based on 2.) | ||
*/ | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
/** | ||
@@ -39,5 +29,4 @@ * For directed graphs. | ||
function _isLeafDirected(inDegree, outDegree) { | ||
return inDegree <= 1 && outDegree < 1; | ||
return inDegree <= 1 && outDegree < 1; | ||
} | ||
/** | ||
@@ -51,6 +40,7 @@ * For not directed graphs. | ||
*/ | ||
function _isLeafNotDirected(inDegree, outDegree) { | ||
return inDegree <= 1 && outDegree <= 1; | ||
return inDegree <= 1 && outDegree <= 1; | ||
} | ||
/** | ||
@@ -64,10 +54,12 @@ * Given in and out degree tells whether degrees indicate a leaf or non leaf scenario. | ||
*/ | ||
function _isLeaf(nodeId, linksMatrix, directed) { | ||
var _computeNodeDegree = computeNodeDegree(nodeId, linksMatrix), | ||
inDegree = _computeNodeDegree.inDegree, | ||
outDegree = _computeNodeDegree.outDegree; | ||
var _computeNodeDegree = computeNodeDegree(nodeId, linksMatrix), | ||
inDegree = _computeNodeDegree.inDegree, | ||
outDegree = _computeNodeDegree.outDegree; | ||
return directed ? _isLeafDirected(inDegree, outDegree) : _isLeafNotDirected(inDegree, outDegree); | ||
var fn = directed ? _isLeafDirected : _isLeafNotDirected; | ||
return fn(inDegree, outDegree); | ||
} | ||
/** | ||
@@ -83,33 +75,28 @@ * Calculates degree (in and out) of some provided node. | ||
*/ | ||
function computeNodeDegree(nodeId) { | ||
var linksMatrix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
return Object.keys(linksMatrix).reduce(function (acc, source) { | ||
if (!linksMatrix[source]) { | ||
return acc; | ||
} | ||
var currentNodeConnections = Object.keys(linksMatrix[source]); | ||
function computeNodeDegree(nodeId) { | ||
var linksMatrix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
return Object.keys(linksMatrix).reduce(function (acc, source) { | ||
if (!linksMatrix[source]) { | ||
return acc; | ||
} | ||
return currentNodeConnections.reduce(function (_acc, target) { | ||
if (nodeId === source) { | ||
return _extends({}, _acc, { | ||
outDegree: _acc.outDegree + linksMatrix[nodeId][target] | ||
}); | ||
} | ||
var currentNodeConnections = Object.keys(linksMatrix[source]); | ||
return currentNodeConnections.reduce(function (_acc, target) { | ||
if (nodeId === source) { | ||
_acc.outDegree += linksMatrix[nodeId][target]; | ||
} | ||
if (nodeId === target) { | ||
return _extends({}, _acc, { | ||
inDegree: _acc.inDegree + linksMatrix[source][nodeId] | ||
}); | ||
} | ||
if (nodeId === target) { | ||
_acc.inDegree += linksMatrix[source][nodeId]; | ||
} | ||
return _acc; | ||
}, acc); | ||
}, { | ||
inDegree: 0, | ||
outDegree: 0 | ||
}); | ||
return _acc; | ||
}, acc); | ||
}, { | ||
inDegree: 0, | ||
outDegree: 0 | ||
}); | ||
} | ||
/** | ||
@@ -127,21 +114,22 @@ * Given a node id we want to calculate the list of leaf connections | ||
*/ | ||
function getTargetLeafConnections(rootNodeId) { | ||
var linksMatrix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var _ref = arguments[2]; | ||
var directed = _ref.directed; | ||
var linksMatrix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var rootConnectionsNodesIds = Object.keys(linksMatrix[rootNodeId]); | ||
var _ref = arguments.length > 2 ? arguments[2] : undefined, | ||
directed = _ref.directed; | ||
return rootConnectionsNodesIds.reduce(function (leafConnections, target) { | ||
if (_isLeaf(target, linksMatrix, directed)) { | ||
leafConnections.push({ | ||
source: rootNodeId, | ||
target: target | ||
}); | ||
} | ||
var rootConnectionsNodesIds = Object.keys(linksMatrix[rootNodeId]); | ||
return rootConnectionsNodesIds.reduce(function (leafConnections, target) { | ||
if (_isLeaf(target, linksMatrix, directed)) { | ||
leafConnections.push({ | ||
source: rootNodeId, | ||
target: target | ||
}); | ||
} | ||
return leafConnections; | ||
}, []); | ||
return leafConnections; | ||
}, []); | ||
} | ||
/** | ||
@@ -152,3 +140,3 @@ * Given a node and the connections matrix, check if node should be displayed | ||
* If you think that this code is confusing and could potentially collide (🤞) with #_isLeaf | ||
* always remember that *A leaf can, through time, be both a visible or an invisible node!*. | ||
* always remember that *A leaf can, throughout time, both a visible or an invisible node!*. | ||
* | ||
@@ -161,12 +149,15 @@ * @param {string} nodeId - The id of the node to get the cardinality of | ||
*/ | ||
function isNodeVisible(nodeId, nodes, linksMatrix) { | ||
var _computeNodeDegree2 = computeNodeDegree(nodeId, linksMatrix), | ||
inDegree = _computeNodeDegree2.inDegree, | ||
outDegree = _computeNodeDegree2.outDegree; | ||
if (nodes[nodeId]._orphan) { | ||
return true; | ||
} | ||
var orphan = !!nodes[nodeId]._orphan; | ||
var _computeNodeDegree2 = computeNodeDegree(nodeId, linksMatrix), | ||
inDegree = _computeNodeDegree2.inDegree, | ||
outDegree = _computeNodeDegree2.outDegree; | ||
return inDegree > 0 || outDegree > 0 || orphan; | ||
return inDegree > 0 || outDegree > 0; | ||
} | ||
/** | ||
@@ -179,16 +170,18 @@ * Updates d3Links by toggling given connections | ||
*/ | ||
function toggleLinksConnections(d3Links, connectionMatrix) { | ||
return d3Links.map(function (d3Link) { | ||
var source = d3Link.source, | ||
target = d3Link.target; | ||
return d3Links.map(function (d3Link) { | ||
var source = d3Link.source, | ||
target = d3Link.target; | ||
var sourceId = (0, _graph.getId)(source); | ||
var targetId = (0, _graph.getId)(target); // connectionMatrix[sourceId][targetId] can be 0 or non existent | ||
var sourceId = source.id || source; | ||
var targetId = target.id || target; | ||
// connectionMatrix[sourceId][targetId] can be 0 or non existent | ||
var connection = connectionMatrix && connectionMatrix[sourceId] && connectionMatrix[sourceId][targetId]; | ||
return connection ? _extends({}, d3Link, { isHidden: false }) : _extends({}, d3Link, { isHidden: true }); | ||
var connection = connectionMatrix && connectionMatrix[sourceId] && connectionMatrix[sourceId][targetId]; | ||
var isHidden = !connection; | ||
return _objectSpread({}, d3Link, { | ||
isHidden: isHidden | ||
}); | ||
}); | ||
} | ||
/** | ||
@@ -204,30 +197,24 @@ * Update matrix given array of connections to toggle. | ||
*/ | ||
function toggleLinksMatrixConnections(linksMatrix, connections, _ref2) { | ||
var directed = _ref2.directed; | ||
return connections.reduce(function (newMatrix, link) { | ||
if (!newMatrix[link.source]) { | ||
newMatrix[link.source] = {}; | ||
} | ||
if (!newMatrix[link.source][link.target]) { | ||
newMatrix[link.source][link.target] = 0; | ||
} | ||
function toggleLinksMatrixConnections(linksMatrix, connections, _ref2) { | ||
var directed = _ref2.directed; | ||
return connections.reduce(function (newMatrix, link) { | ||
if (!newMatrix[link.source]) { | ||
newMatrix[link.source] = {}; | ||
} | ||
var newConnectionValue = newMatrix[link.source][link.target] === 0 ? 1 : 0; | ||
if (!newMatrix[link.source][link.target]) { | ||
newMatrix[link.source][link.target] = 0; | ||
} | ||
newMatrix[link.source][link.target] = newConnectionValue; | ||
var newConnectionValue = newMatrix[link.source][link.target] === 0 ? 1 : 0; | ||
newMatrix[link.source][link.target] = newConnectionValue; | ||
if (!directed) { | ||
newMatrix[link.target][link.source] = newConnectionValue; | ||
} | ||
if (!directed) { | ||
newMatrix[link.target][link.source] = newConnectionValue; | ||
} | ||
return newMatrix; | ||
}, _extends({}, linksMatrix)); | ||
} | ||
exports.computeNodeDegree = computeNodeDegree; | ||
exports.getTargetLeafConnections = getTargetLeafConnections; | ||
exports.isNodeVisible = isNodeVisible; | ||
exports.toggleLinksConnections = toggleLinksConnections; | ||
exports.toggleLinksMatrixConnections = toggleLinksMatrixConnections; | ||
return newMatrix; | ||
}, _objectSpread({}, linksMatrix)); | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.buildNodeProps = exports.buildLinkProps = undefined; | ||
exports.buildLinkProps = buildLinkProps; | ||
exports.buildNodeProps = buildNodeProps; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** | ||
* @module Graph/builder | ||
* @description | ||
* Offers a series of methods that isolate the way graph elements are built (nodes and links mainly). | ||
*/ | ||
var _graph = _interopRequireDefault(require("./graph.const")); | ||
var _link = require("../link/link.helper"); | ||
var _graph = require("./graph.const"); | ||
var _marker = require("../marker/marker.helper"); | ||
var _graph2 = _interopRequireDefault(_graph); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _link = require("../link/link.helper"); | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
var _marker = require("../marker/marker.helper"); | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -35,17 +33,17 @@ /** | ||
function _getNodeOpacity(node, highlightedNode, highlightedLink, config) { | ||
var highlight = node.highlighted || node.id === (highlightedLink && highlightedLink.source) || node.id === (highlightedLink && highlightedLink.target); | ||
var someNodeHighlighted = !!(highlightedNode || highlightedLink && highlightedLink.source && highlightedLink.target); | ||
var opacity = void 0; | ||
var highlight = node.highlighted || node.id === (highlightedLink && highlightedLink.source) || node.id === (highlightedLink && highlightedLink.target); | ||
var someLinkHighlighted = highlightedLink && highlightedLink.source && highlightedLink.target; | ||
var someNodeHighlighted = !!(highlightedNode || someLinkHighlighted); | ||
var opacity; | ||
if (someNodeHighlighted && config.highlightDegree === 0) { | ||
opacity = highlight ? config.node.opacity : config.highlightOpacity; | ||
} else if (someNodeHighlighted) { | ||
opacity = highlight ? config.node.opacity : config.highlightOpacity; | ||
} else { | ||
opacity = node.opacity || config.node.opacity; | ||
} | ||
if (someNodeHighlighted && config.highlightDegree === 0) { | ||
opacity = highlight ? config.node.opacity : config.highlightOpacity; | ||
} else if (someNodeHighlighted) { | ||
opacity = highlight ? config.node.opacity : config.highlightOpacity; | ||
} else { | ||
opacity = node.opacity || config.node.opacity; | ||
} | ||
return opacity; | ||
return opacity; | ||
} | ||
/** | ||
@@ -64,93 +62,100 @@ * Build some Link properties based on given parameters. | ||
*/ | ||
function buildLinkProps(link, nodes, links, config, linkCallbacks, highlightedNode, highlightedLink, transform) { | ||
var source = link.source, | ||
target = link.target; | ||
var x1 = nodes[source] && nodes[source].x || 0; | ||
var y1 = nodes[source] && nodes[source].y || 0; | ||
var x2 = nodes[target] && nodes[target].x || 0; | ||
var y2 = nodes[target] && nodes[target].y || 0; | ||
var d = (0, _link.buildLinkPathDefinition)({ source: { x: x1, y: y1 }, target: { x: x2, y: y2 } }, config.link.type); | ||
function buildLinkProps(link, nodes, links, config, linkCallbacks, highlightedNode, highlightedLink, transform) { | ||
var _nodes$source, _nodes$source2, _nodes$target, _nodes$target2; | ||
var mainNodeParticipates = false; | ||
switch (config.highlightDegree) { | ||
case 0: | ||
break; | ||
case 2: | ||
mainNodeParticipates = true; | ||
break; | ||
default: | ||
// 1st degree is the fallback behavior | ||
mainNodeParticipates = source === highlightedNode || target === highlightedNode; | ||
break; | ||
var source = link.source, | ||
target = link.target; | ||
var x1 = (nodes === null || nodes === void 0 ? void 0 : (_nodes$source = nodes[source]) === null || _nodes$source === void 0 ? void 0 : _nodes$source.x) || 0; | ||
var y1 = (nodes === null || nodes === void 0 ? void 0 : (_nodes$source2 = nodes[source]) === null || _nodes$source2 === void 0 ? void 0 : _nodes$source2.y) || 0; | ||
var x2 = (nodes === null || nodes === void 0 ? void 0 : (_nodes$target = nodes[target]) === null || _nodes$target === void 0 ? void 0 : _nodes$target.x) || 0; | ||
var y2 = (nodes === null || nodes === void 0 ? void 0 : (_nodes$target2 = nodes[target]) === null || _nodes$target2 === void 0 ? void 0 : _nodes$target2.y) || 0; | ||
var d = (0, _link.buildLinkPathDefinition)({ | ||
source: { | ||
x: x1, | ||
y: y1 | ||
}, | ||
target: { | ||
x: x2, | ||
y: y2 | ||
} | ||
}, config.link.type); | ||
var mainNodeParticipates = false; | ||
var reasonNode = mainNodeParticipates && nodes[source].highlighted && nodes[target].highlighted; | ||
var reasonLink = source === (highlightedLink && highlightedLink.source) && target === (highlightedLink && highlightedLink.target); | ||
var highlight = reasonNode || reasonLink; | ||
switch (config.highlightDegree) { | ||
case 0: | ||
break; | ||
var opacity = link.opacity || config.link.opacity; | ||
case 2: | ||
mainNodeParticipates = true; | ||
break; | ||
if (highlightedNode || highlightedLink && highlightedLink.source) { | ||
opacity = highlight ? config.link.opacity : config.highlightOpacity; | ||
} | ||
default: | ||
// 1st degree is the fallback behavior | ||
mainNodeParticipates = source === highlightedNode || target === highlightedNode; | ||
break; | ||
} | ||
var stroke = link.color || config.link.color; | ||
var guiltyNode = mainNodeParticipates && nodes[source].highlighted && nodes[target].highlighted; | ||
var guiltyLink = source === (highlightedLink && highlightedLink.source) && target === (highlightedLink && highlightedLink.target); | ||
var highlight = guiltyNode || guiltyLink; | ||
var opacity = link.opacity || config.link.opacity; | ||
if (highlight) { | ||
stroke = config.link.highlightColor === _graph2.default.KEYWORDS.SAME ? config.link.color : config.link.highlightColor; | ||
} | ||
if (highlightedNode || highlightedLink && highlightedLink.source) { | ||
opacity = highlight ? config.link.opacity : config.highlightOpacity; | ||
} | ||
var strokeWidth = (link.strokeWidth || config.link.strokeWidth) * (1 / transform); | ||
var stroke = link.color || config.link.color; | ||
if (config.link.semanticStrokeWidth) { | ||
var linkValue = links[source][target] || links[target][source] || 1; | ||
if (highlight) { | ||
stroke = config.link.highlightColor === _graph["default"].KEYWORDS.SAME ? config.link.color : config.link.highlightColor; | ||
} | ||
strokeWidth += linkValue * strokeWidth / 10; | ||
} | ||
var strokeWidth = (link.strokeWidth || config.link.strokeWidth) * (1 / transform); | ||
var markerId = config.directed ? (0, _marker.getMarkerId)(highlight, transform, config) : null; | ||
if (config.link.semanticStrokeWidth) { | ||
var linkValue = links[source][target] || links[target][source] || 1; | ||
strokeWidth += linkValue * strokeWidth / 10; | ||
} | ||
var t = 1 / transform; | ||
var markerId = config.directed ? (0, _marker.getMarkerId)(highlight, transform, config) : null; | ||
var t = 1 / transform; | ||
var fontSize = null, | ||
fontColor = null, | ||
fontWeight = null, | ||
label = null; | ||
var fontSize = null; | ||
var fontColor = null; | ||
var fontWeight = null; | ||
var label = null; | ||
if (config.link.renderLabel) { | ||
if (typeof config.link.labelProperty === "function") { | ||
label = config.link.labelProperty(link); | ||
} else { | ||
label = link[config.link.labelProperty]; | ||
} | ||
if (config.link.renderLabel) { | ||
if (typeof config.link.labelProperty === "function") { | ||
label = config.link.labelProperty(link); | ||
} else { | ||
label = link[config.link.labelProperty]; | ||
} | ||
fontSize = link.fontSize || config.link.fontSize; | ||
fontColor = link.fontColor || config.link.fontColor; | ||
fontWeight = highlight ? config.link.highlightFontWeight : config.link.fontWeight; | ||
} | ||
fontSize = link.fontSize || config.link.fontSize; | ||
fontColor = link.fontColor || config.link.fontColor; | ||
fontWeight = highlight ? config.link.highlightFontWeight : config.link.fontWeight; | ||
} | ||
return { | ||
markerId: markerId, | ||
d: d, | ||
source: source, | ||
target: target, | ||
strokeWidth: strokeWidth, | ||
stroke: stroke, | ||
label: label, | ||
mouseCursor: config.link.mouseCursor, | ||
fontColor: fontColor, | ||
fontSize: fontSize * t, | ||
fontWeight: fontWeight, | ||
className: _graph2.default.LINK_CLASS_NAME, | ||
opacity: opacity, | ||
onClickLink: linkCallbacks.onClickLink, | ||
onRightClickLink: linkCallbacks.onRightClickLink, | ||
onMouseOverLink: linkCallbacks.onMouseOverLink, | ||
onMouseOutLink: linkCallbacks.onMouseOutLink | ||
}; | ||
return { | ||
className: _graph["default"].LINK_CLASS_NAME, | ||
d: d, | ||
fontColor: fontColor, | ||
fontSize: fontSize * t, | ||
fontWeight: fontWeight, | ||
label: label, | ||
markerId: markerId, | ||
mouseCursor: config.link.mouseCursor, | ||
opacity: opacity, | ||
source: source, | ||
stroke: stroke, | ||
strokeWidth: strokeWidth, | ||
target: target, | ||
onClickLink: linkCallbacks.onClickLink, | ||
onMouseOutLink: linkCallbacks.onMouseOutLink, | ||
onMouseOverLink: linkCallbacks.onMouseOverLink, | ||
onRightClickLink: linkCallbacks.onRightClickLink | ||
}; | ||
} | ||
/** | ||
@@ -167,71 +172,69 @@ * Build some Node properties based on given parameters. | ||
*/ | ||
function buildNodeProps(node, config) { | ||
var nodeCallbacks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
var highlightedNode = arguments[3]; | ||
var highlightedLink = arguments[4]; | ||
var transform = arguments[5]; | ||
var highlight = node.highlighted || node.id === (highlightedLink && highlightedLink.source) || node.id === (highlightedLink && highlightedLink.target); | ||
var opacity = _getNodeOpacity(node, highlightedNode, highlightedLink, config); | ||
var fill = node.color || config.node.color; | ||
function buildNodeProps(node, config) { | ||
var nodeCallbacks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
var highlightedNode = arguments.length > 3 ? arguments[3] : undefined; | ||
var highlightedLink = arguments.length > 4 ? arguments[4] : undefined; | ||
var transform = arguments.length > 5 ? arguments[5] : undefined; | ||
var highlight = node.highlighted || node.id === (highlightedLink && highlightedLink.source) || node.id === (highlightedLink && highlightedLink.target); | ||
if (highlight && config.node.highlightColor !== _graph2.default.KEYWORDS.SAME) { | ||
fill = config.node.highlightColor; | ||
} | ||
var opacity = _getNodeOpacity(node, highlightedNode, highlightedLink, config); | ||
var stroke = node.strokeColor || config.node.strokeColor; | ||
var fill = node.color || config.node.color; | ||
if (highlight && config.node.highlightStrokeColor !== _graph2.default.KEYWORDS.SAME) { | ||
stroke = config.node.highlightStrokeColor; | ||
} | ||
if (highlight && config.node.highlightColor !== _graph["default"].KEYWORDS.SAME) { | ||
fill = config.node.highlightColor; | ||
} | ||
var label = node[config.node.labelProperty] || node.id; | ||
var stroke = node.strokeColor || config.node.strokeColor; | ||
if (typeof config.node.labelProperty === "function") { | ||
label = config.node.labelProperty(node); | ||
} | ||
if (highlight && config.node.highlightStrokeColor !== _graph["default"].KEYWORDS.SAME) { | ||
stroke = config.node.highlightStrokeColor; | ||
} | ||
var strokeWidth = node.strokeWidth || config.node.strokeWidth; | ||
var label = node[config.node.labelProperty] || node.id; | ||
if (highlight && config.node.highlightStrokeWidth !== _graph2.default.KEYWORDS.SAME) { | ||
strokeWidth = config.node.highlightStrokeWidth; | ||
} | ||
if (typeof config.node.labelProperty === "function") { | ||
label = config.node.labelProperty(node); | ||
} | ||
var t = 1 / transform; | ||
var nodeSize = node.size || config.node.size; | ||
var fontSize = highlight ? config.node.highlightFontSize : config.node.fontSize; | ||
var dx = fontSize * t + nodeSize / 100 + 1.5; | ||
var svg = node.svg || config.node.svg; | ||
var fontColor = node.fontColor || config.node.fontColor; | ||
var strokeWidth = node.strokeWidth || config.node.strokeWidth; | ||
return _extends({}, node, { | ||
className: _graph2.default.NODE_CLASS_NAME, | ||
cursor: config.node.mouseCursor, | ||
cx: node && node.x || "0", | ||
cy: node && node.y || "0", | ||
fill: fill, | ||
fontColor: fontColor, | ||
fontSize: fontSize * t, | ||
dx: dx, | ||
fontWeight: highlight ? config.node.highlightFontWeight : config.node.fontWeight, | ||
id: node.id, | ||
label: label, | ||
onClickNode: nodeCallbacks.onClickNode, | ||
onRightClickNode: nodeCallbacks.onRightClickNode, | ||
onMouseOverNode: nodeCallbacks.onMouseOverNode, | ||
onMouseOut: nodeCallbacks.onMouseOut, | ||
opacity: opacity, | ||
renderLabel: config.node.renderLabel, | ||
size: nodeSize * t, | ||
stroke: stroke, | ||
strokeWidth: strokeWidth * t, | ||
svg: svg, | ||
type: node.symbolType || config.node.symbolType, | ||
viewGenerator: node.viewGenerator || config.node.viewGenerator, | ||
overrideGlobalViewGenerator: !node.viewGenerator && node.svg | ||
}); | ||
} | ||
if (highlight && config.node.highlightStrokeWidth !== _graph["default"].KEYWORDS.SAME) { | ||
strokeWidth = config.node.highlightStrokeWidth; | ||
} | ||
exports.buildLinkProps = buildLinkProps; | ||
exports.buildNodeProps = buildNodeProps; | ||
var t = 1 / transform; | ||
var nodeSize = node.size || config.node.size; | ||
var fontSize = highlight ? config.node.highlightFontSize : config.node.fontSize; | ||
var dx = fontSize * t + nodeSize / 100 + 1.5; | ||
var svg = node.svg || config.node.svg; | ||
var fontColor = node.fontColor || config.node.fontColor; | ||
return _objectSpread({}, node, { | ||
className: _graph["default"].NODE_CLASS_NAME, | ||
cursor: config.node.mouseCursor, | ||
cx: (node === null || node === void 0 ? void 0 : node.x) || "0", | ||
cy: (node === null || node === void 0 ? void 0 : node.y) || "0", | ||
dx: dx, | ||
fill: fill, | ||
fontColor: fontColor, | ||
fontSize: fontSize * t, | ||
fontWeight: highlight ? config.node.highlightFontWeight : config.node.fontWeight, | ||
id: node.id, | ||
label: label, | ||
opacity: opacity, | ||
overrideGlobalViewGenerator: !node.viewGenerator && node.svg, | ||
renderLabel: config.node.renderLabel, | ||
size: nodeSize * t, | ||
stroke: stroke, | ||
strokeWidth: strokeWidth * t, | ||
svg: svg, | ||
type: node.symbolType || config.node.symbolType, | ||
viewGenerator: node.viewGenerator || config.node.viewGenerator, | ||
onClickNode: nodeCallbacks.onClickNode, | ||
onMouseOut: nodeCallbacks.onMouseOut, | ||
onMouseOverNode: nodeCallbacks.onMouseOverNode, | ||
onRightClickNode: nodeCallbacks.onRightClickNode | ||
}); | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
/** | ||
@@ -215,63 +217,64 @@ * <div style="text-align: right;"><i>This is certainly the only extra piece of documentation that you will ever need</i></div> | ||
*/ | ||
exports.default = { | ||
automaticRearrangeAfterDropNode: false, | ||
collapsible: false, | ||
directed: false, | ||
focusAnimationDuration: 0.75, | ||
focusZoom: 1, | ||
height: 400, | ||
highlightDegree: 1, | ||
highlightOpacity: 1, | ||
linkHighlightBehavior: false, | ||
maxZoom: 8, | ||
minZoom: 0.1, | ||
nodeHighlightBehavior: false, | ||
panAndZoom: false, | ||
staticGraph: false, | ||
staticGraphWithDragAndDrop: false, | ||
width: 800, | ||
d3: { | ||
alphaTarget: 0.05, | ||
gravity: -100, | ||
linkLength: 100, | ||
linkStrength: 1 | ||
}, | ||
node: { | ||
color: "#d3d3d3", | ||
fontColor: "black", | ||
fontSize: 8, | ||
fontWeight: "normal", | ||
highlightColor: "SAME", | ||
highlightFontSize: 8, | ||
highlightFontWeight: "normal", | ||
highlightStrokeColor: "SAME", | ||
highlightStrokeWidth: "SAME", | ||
labelProperty: "id", | ||
mouseCursor: "pointer", | ||
opacity: 1, | ||
renderLabel: true, | ||
size: 200, | ||
strokeColor: "none", | ||
strokeWidth: 1.5, | ||
svg: "", | ||
symbolType: "circle", | ||
viewGenerator: null | ||
}, | ||
link: { | ||
color: "#d3d3d3", | ||
fontColor: "black", | ||
fontSize: 8, | ||
fontWeight: "normal", | ||
// FIXME: highlightColor default should be "SAME", breaking change | ||
highlightColor: "#d3d3d3", | ||
highlightFontSize: 8, | ||
highlightFontWeight: "normal", | ||
labelProperty: "label", | ||
mouseCursor: "pointer", | ||
opacity: 1, | ||
renderLabel: false, | ||
semanticStrokeWidth: false, | ||
strokeWidth: 1.5, | ||
type: "STRAIGHT" | ||
} | ||
}; | ||
var _default = { | ||
automaticRearrangeAfterDropNode: false, | ||
collapsible: false, | ||
directed: false, | ||
focusAnimationDuration: 0.75, | ||
focusZoom: 1, | ||
height: 400, | ||
highlightDegree: 1, | ||
highlightOpacity: 1, | ||
linkHighlightBehavior: false, | ||
maxZoom: 8, | ||
minZoom: 0.1, | ||
nodeHighlightBehavior: false, | ||
panAndZoom: false, | ||
staticGraph: false, | ||
staticGraphWithDragAndDrop: false, | ||
width: 800, | ||
d3: { | ||
alphaTarget: 0.05, | ||
gravity: -100, | ||
linkLength: 100, | ||
linkStrength: 1 | ||
}, | ||
node: { | ||
color: "#d3d3d3", | ||
fontColor: "black", | ||
fontSize: 8, | ||
fontWeight: "normal", | ||
highlightColor: "SAME", | ||
highlightFontSize: 8, | ||
highlightFontWeight: "normal", | ||
highlightStrokeColor: "SAME", | ||
highlightStrokeWidth: "SAME", | ||
labelProperty: "id", | ||
mouseCursor: "pointer", | ||
opacity: 1, | ||
renderLabel: true, | ||
size: 200, | ||
strokeColor: "none", | ||
strokeWidth: 1.5, | ||
svg: "", | ||
symbolType: "circle", | ||
viewGenerator: null | ||
}, | ||
link: { | ||
color: "#d3d3d3", | ||
fontColor: "black", | ||
fontSize: 8, | ||
fontWeight: "normal", | ||
// FIXME: highlightColor default should be "SAME", breaking change | ||
highlightColor: "#d3d3d3", | ||
highlightFontSize: 8, | ||
highlightFontWeight: "normal", | ||
labelProperty: "label", | ||
mouseCursor: "pointer", | ||
opacity: 1, | ||
renderLabel: false, | ||
semanticStrokeWidth: false, | ||
strokeWidth: 1.5, | ||
type: "STRAIGHT" | ||
} | ||
}; | ||
exports["default"] = _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _const = _interopRequireDefault(require("../../const")); | ||
var _const = require("../../const"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _const2 = _interopRequireDefault(_const); | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
exports.default = _extends({ | ||
COORDS_SEPARATOR: ",", | ||
FORCE_X: 0.06, | ||
FORCE_Y: 0.06, | ||
GRAPH_CONTAINER_ID: "graph-container-zoomable", | ||
GRAPH_WRAPPER_ID: "graph-wrapper", | ||
KEYWORDS: { | ||
SAME: "SAME" | ||
}, | ||
LINK_CLASS_NAME: "link", | ||
NODE_CLASS_NAME: "node", | ||
TTL_DOUBLE_CLICK_IN_MS: 300 | ||
}, _const2.default); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var _default = _objectSpread({ | ||
COORDS_SEPARATOR: ",", | ||
FORCE_X: 0.06, | ||
FORCE_Y: 0.06, | ||
GRAPH_CONTAINER_ID: "graph-container-zoomable", | ||
GRAPH_WRAPPER_ID: "graph-wrapper", | ||
KEYWORDS: { | ||
SAME: "SAME" | ||
}, | ||
LINK_CLASS_NAME: "link", | ||
NODE_CLASS_NAME: "node", | ||
TTL_DOUBLE_CLICK_IN_MS: 300 | ||
}, _const["default"]); | ||
exports["default"] = _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.updateNodeHighlightedValue = exports.initializeGraphState = exports.getCenterAndZoomTransformation = exports.checkForGraphElementsChanges = exports.checkForGraphConfigChanges = undefined; | ||
exports.checkForGraphConfigChanges = checkForGraphConfigChanges; | ||
exports.checkForGraphElementsChanges = checkForGraphElementsChanges; | ||
exports.getCenterAndZoomTransformation = getCenterAndZoomTransformation; | ||
exports.getId = getId; | ||
exports.initializeGraphState = initializeGraphState; | ||
exports.updateNodeHighlightedValue = updateNodeHighlightedValue; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** | ||
* @module Graph/helper | ||
* @description | ||
* Offers a series of methods that isolate logic of Graph component and also from Graph rendering methods. | ||
*/ | ||
/** | ||
* @typedef {Object} Link | ||
* @property {string} source - the node id of the source in the link. | ||
* @property {string} target - the node id of the target in the link. | ||
* @memberof Graph/helper | ||
*/ | ||
/** | ||
* @typedef {Object} Node | ||
* @property {string} id - the id of the node. | ||
* @property {string} [color=] - color of the node (optional). | ||
* @property {string} [fontColor=] - node text label font color (optional). | ||
* @property {string} [size=] - size of the node (optional). | ||
* @property {string} [symbolType=] - symbol type of the node (optional). | ||
* @property {string} [svg=] - custom svg for node (optional). | ||
* @memberof Graph/helper | ||
*/ | ||
var _d3Force = require("d3-force"); | ||
var _graph2 = require("./graph.const"); | ||
var _graph2 = _interopRequireDefault(require("./graph.const")); | ||
var _graph3 = _interopRequireDefault(_graph2); | ||
var _graph3 = _interopRequireDefault(require("./graph.config")); | ||
var _graph4 = require("./graph.config"); | ||
var _err = _interopRequireDefault(require("../../err")); | ||
var _graph5 = _interopRequireDefault(_graph4); | ||
var _utils = require("../../utils"); | ||
var _err = require("../../err"); | ||
var _collapse = require("./collapse.helper"); | ||
var _err2 = _interopRequireDefault(_err); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _utils = require("../../utils"); | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
var _utils2 = _interopRequireDefault(_utils); | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
var _collapse = require("./collapse.helper"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -57,3 +35,2 @@ | ||
var LINK_PROPS_WHITELIST = ["index", "source", "target", "isHidden"]; | ||
/** | ||
@@ -70,10 +47,9 @@ * Create d3 forceSimulation to be applied on the graph.<br/> | ||
*/ | ||
function _createForceSimulation(width, height, gravity) { | ||
var frx = (0, _d3Force.forceX)(width / 2).strength(_graph3.default.FORCE_X); | ||
var fry = (0, _d3Force.forceY)(height / 2).strength(_graph3.default.FORCE_Y); | ||
var forceStrength = gravity; | ||
return (0, _d3Force.forceSimulation)().force("charge", (0, _d3Force.forceManyBody)().strength(forceStrength)).force("x", frx).force("y", fry); | ||
var frx = (0, _d3Force.forceX)(width / 2).strength(_graph2["default"].FORCE_X); | ||
var fry = (0, _d3Force.forceY)(height / 2).strength(_graph2["default"].FORCE_Y); | ||
var forceStrength = gravity; | ||
return (0, _d3Force.forceSimulation)().force("charge", (0, _d3Force.forceManyBody)().strength(forceStrength)).force("x", frx).force("y", fry); | ||
} | ||
/** | ||
@@ -89,27 +65,27 @@ * Receives a matrix of the graph with the links source and target as concrete node instances and it transforms it | ||
*/ | ||
function _initializeLinks(graphLinks, config) { | ||
return graphLinks.reduce(function (links, l) { | ||
var source = l.source.id !== undefined && l.source.id !== null ? l.source.id : l.source; | ||
var target = l.target.id !== undefined && l.target.id !== null ? l.target.id : l.target; | ||
return graphLinks.reduce(function (links, l) { | ||
var source = getId(l.source); | ||
var target = getId(l.target); | ||
if (!links[source]) { | ||
links[source] = {}; | ||
} | ||
if (!links[source]) { | ||
links[source] = {}; | ||
} | ||
if (!links[target]) { | ||
links[target] = {}; | ||
} | ||
if (!links[target]) { | ||
links[target] = {}; | ||
} | ||
var value = config.collapsible && l.isHidden ? 0 : l.value || 1; | ||
var value = config.collapsible && l.isHidden ? 0 : l.value || 1; | ||
links[source][target] = value; | ||
links[source][target] = value; | ||
if (!config.directed) { | ||
links[target][source] = value; | ||
} | ||
if (!config.directed) { | ||
links[target][source] = value; | ||
} | ||
return links; | ||
}, {}); | ||
return links; | ||
}, {}); | ||
} | ||
/** | ||
@@ -124,24 +100,25 @@ * Method that initialize graph nodes provided by rd3g consumer and adds additional default mandatory properties | ||
*/ | ||
function _initializeNodes(graphNodes) { | ||
var nodes = {}; | ||
var n = graphNodes.length; | ||
for (var i = 0; i < n; i++) { | ||
var node = graphNodes[i]; | ||
node.highlighted = false; | ||
function _initializeNodes(graphNodes) { | ||
var nodes = {}; | ||
var n = graphNodes.length; | ||
if (!node.hasOwnProperty("x")) { | ||
node.x = 0; | ||
} | ||
if (!node.hasOwnProperty("y")) { | ||
node.y = 0; | ||
} | ||
for (var i = 0; i < n; i++) { | ||
var node = graphNodes[i]; | ||
node.highlighted = false; | ||
nodes[node.id.toString()] = node; | ||
if (!Object.prototype.hasOwnProperty.call(node, "x")) { | ||
node.x = 0; | ||
} | ||
return nodes; | ||
if (!Object.prototype.hasOwnProperty.call(node, "y")) { | ||
node.y = 0; | ||
} | ||
nodes[node.id.toString()] = node; | ||
} | ||
return nodes; | ||
} | ||
/** | ||
@@ -159,46 +136,50 @@ * Maps an input link (with format `{ source: 'sourceId', target: 'targetId' }`) to a d3Link | ||
*/ | ||
function _mergeDataLinkWithD3Link(link, index) { | ||
var d3Links = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; | ||
var config = arguments[3]; | ||
var state = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; | ||
var d3Links = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; | ||
var config = arguments.length > 3 ? arguments[3] : undefined; | ||
var state = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; | ||
// find the matching link if it exists | ||
var tmp = d3Links.find(function (l) { | ||
return l.source.id === link.source && l.target.id === link.target; | ||
}); | ||
var d3Link = tmp && (0, _utils.pick)(tmp, LINK_PROPS_WHITELIST); | ||
var customProps = (0, _utils.antiPick)(link, ["source", "target"]); | ||
// find the matching link if it exists | ||
var tmp = d3Links.find(function (l) { | ||
return l.source.id === link.source && l.target.id === link.target; | ||
}); | ||
var d3Link = tmp && _utils2.default.pick(tmp, LINK_PROPS_WHITELIST); | ||
var customProps = _utils2.default.antiPick(link, ["source", "target"]); | ||
if (d3Link) { | ||
var toggledDirected = state.config && Object.prototype.hasOwnProperty.call(state.config, "directed") && config.directed !== state.config.directed; | ||
if (d3Link) { | ||
var toggledDirected = state.config && state.config.hasOwnProperty("directed") && config.directed !== state.config.directed; | ||
var refinedD3Link = _extends({ | ||
index: index | ||
}, d3Link, customProps); | ||
var refinedD3Link = _objectSpread({ | ||
index: index | ||
}, d3Link, {}, customProps); // every time we toggle directed config all links should be visible again | ||
// every time we toggle directed config all links should be visible again | ||
if (toggledDirected) { | ||
return _extends({}, refinedD3Link, { isHidden: false }); | ||
} | ||
// every time we disable collapsible (collapsible is false) all links should be visible again | ||
return config.collapsible ? refinedD3Link : _extends({}, refinedD3Link, { isHidden: false }); | ||
} | ||
if (toggledDirected) { | ||
return _objectSpread({}, refinedD3Link, { | ||
isHidden: false | ||
}); | ||
} // every time we disable collapsible (collapsible is false) all links should be visible again | ||
var highlighted = false; | ||
var source = { | ||
id: link.source, | ||
highlighted: highlighted | ||
}; | ||
var target = { | ||
id: link.target, | ||
highlighted: highlighted | ||
}; | ||
return _extends({ | ||
index: index, | ||
source: source, | ||
target: target | ||
}, customProps); | ||
return config.collapsible ? refinedD3Link : _objectSpread({}, refinedD3Link, { | ||
isHidden: false | ||
}); | ||
} | ||
var highlighted = false; | ||
var source = { | ||
id: link.source, | ||
highlighted: highlighted | ||
}; | ||
var target = { | ||
id: link.target, | ||
highlighted: highlighted | ||
}; | ||
return _objectSpread({ | ||
index: index, | ||
source: source, | ||
target: target | ||
}, customProps); | ||
} | ||
/** | ||
@@ -212,17 +193,18 @@ * Tags orphan nodes with a `_orphan` flag. | ||
*/ | ||
function _tagOrphanNodes(nodes, linksMatrix) { | ||
return Object.keys(nodes).reduce(function (acc, nodeId) { | ||
var _computeNodeDegree = (0, _collapse.computeNodeDegree)(nodeId, linksMatrix), | ||
inDegree = _computeNodeDegree.inDegree, | ||
outDegree = _computeNodeDegree.outDegree; | ||
var node = nodes[nodeId]; | ||
var taggedNode = inDegree === 0 && outDegree === 0 ? _extends({}, node, { _orphan: true }) : node; | ||
acc[nodeId] = taggedNode; | ||
function _tagOrphanNodes(nodes, linksMatrix) { | ||
return Object.keys(nodes).reduce(function (acc, nodeId) { | ||
var _computeNodeDegree = (0, _collapse.computeNodeDegree)(nodeId, linksMatrix), | ||
inDegree = _computeNodeDegree.inDegree, | ||
outDegree = _computeNodeDegree.outDegree; | ||
return acc; | ||
}, {}); | ||
var node = nodes[nodeId]; | ||
var taggedNode = inDegree === 0 && outDegree === 0 ? _objectSpread({}, node, { | ||
_orphan: true | ||
}) : node; | ||
acc[nodeId] = taggedNode; | ||
return acc; | ||
}, {}); | ||
} | ||
/** | ||
@@ -238,37 +220,38 @@ * Some integrity validations on links and nodes structure. If some validation fails the function will | ||
*/ | ||
function _validateGraphData(data) { | ||
if (!data.nodes || !data.nodes.length) { | ||
_utils2.default.throwErr("Graph", _err2.default.INSUFFICIENT_DATA); | ||
} | ||
var n = data.links.length; | ||
var _loop = function _loop(i) { | ||
var l = data.links[i]; | ||
function _validateGraphData(data) { | ||
if (!data.nodes || !data.nodes.length) { | ||
(0, _utils.throwErr)("Graph", _err["default"].INSUFFICIENT_DATA); | ||
} | ||
if (!data.nodes.find(function (n) { | ||
return n.id === l.source; | ||
})) { | ||
_utils2.default.throwErr("Graph", _err2.default.INVALID_LINKS + " - \"" + l.source + "\" is not a valid source node id"); | ||
} | ||
var n = data.links.length; | ||
if (!data.nodes.find(function (n) { | ||
return n.id === l.target; | ||
})) { | ||
_utils2.default.throwErr("Graph", _err2.default.INVALID_LINKS + " - \"" + l.target + "\" is not a valid target node id"); | ||
} | ||
var _loop = function _loop(i) { | ||
var l = data.links[i]; | ||
if (l && l.value !== undefined && typeof l.value !== "number") { | ||
_utils2.default.throwErr("Graph", _err2.default.INVALID_LINK_VALUE + " - found in link with source \"" + l.source + "\" and target \"" + l.target + "\""); | ||
} | ||
}; | ||
if (!data.nodes.find(function (n) { | ||
return n.id === l.source; | ||
})) { | ||
(0, _utils.throwErr)("Graph", "".concat(_err["default"].INVALID_LINKS, " - \"").concat(l.source, "\" is not a valid source node id")); | ||
} | ||
for (var i = 0; i < n; i++) { | ||
_loop(i); | ||
if (!data.nodes.find(function (n) { | ||
return n.id === l.target; | ||
})) { | ||
(0, _utils.throwErr)("Graph", "".concat(_err["default"].INVALID_LINKS, " - \"").concat(l.target, "\" is not a valid target node id")); | ||
} | ||
} | ||
// list of properties that are of no interest when it comes to nodes and links comparison | ||
if (l && l.value !== undefined && typeof l.value !== "number") { | ||
(0, _utils.throwErr)("Graph", "".concat(_err["default"].INVALID_LINK_VALUE, " - found in link with source \"").concat(l.source, "\" and target \"").concat(l.target, "\"")); | ||
} | ||
}; | ||
for (var i = 0; i < n; i++) { | ||
_loop(i); | ||
} | ||
} // list of properties that are of no interest when it comes to nodes and links comparison | ||
var NODE_PROPERTIES_DISCARD_TO_COMPARE = ["x", "y", "vx", "vy", "index"]; | ||
/** | ||
@@ -280,6 +263,6 @@ * Picks the id. | ||
*/ | ||
function _pickId(o) { | ||
return _utils2.default.pick(o, ["id"]); | ||
return (0, _utils.pick)(o, ["id"]); | ||
} | ||
/** | ||
@@ -291,6 +274,7 @@ * Picks source and target. | ||
*/ | ||
function _pickSourceAndTarget(o) { | ||
return _utils2.default.pick(o, ["source", "target"]); | ||
return (0, _utils.pick)(o, ["source", "target"]); | ||
} | ||
/** | ||
@@ -309,23 +293,25 @@ * This function checks for graph elements (nodes and links) changes, in two different | ||
*/ | ||
function checkForGraphElementsChanges(nextProps, currentState) { | ||
var nextNodes = nextProps.data.nodes.map(function (n) { | ||
return _utils2.default.antiPick(n, NODE_PROPERTIES_DISCARD_TO_COMPARE); | ||
}); | ||
var nextLinks = nextProps.data.links; | ||
var stateD3Nodes = currentState.d3Nodes.map(function (n) { | ||
return _utils2.default.antiPick(n, NODE_PROPERTIES_DISCARD_TO_COMPARE); | ||
}); | ||
var stateD3Links = currentState.d3Links.map(function (l) { | ||
return { | ||
// FIXME: solve this source data inconsistency later | ||
source: l.source.id !== undefined && l.source.id !== null ? l.source.id : l.source, | ||
target: l.target.id !== undefined && l.target.id !== null ? l.target.id : l.target | ||
}; | ||
}); | ||
var graphElementsUpdated = !(_utils2.default.isDeepEqual(nextNodes, stateD3Nodes) && _utils2.default.isDeepEqual(nextLinks, stateD3Links)); | ||
var newGraphElements = nextNodes.length !== stateD3Nodes.length || nextLinks.length !== stateD3Links.length || !_utils2.default.isDeepEqual(nextNodes.map(_pickId), stateD3Nodes.map(_pickId)) || !_utils2.default.isDeepEqual(nextLinks.map(_pickSourceAndTarget), stateD3Links.map(_pickSourceAndTarget)); | ||
return { graphElementsUpdated: graphElementsUpdated, newGraphElements: newGraphElements }; | ||
var nextNodes = nextProps.data.nodes.map(function (n) { | ||
return (0, _utils.antiPick)(n, NODE_PROPERTIES_DISCARD_TO_COMPARE); | ||
}); | ||
var nextLinks = nextProps.data.links; | ||
var stateD3Nodes = currentState.d3Nodes.map(function (n) { | ||
return (0, _utils.antiPick)(n, NODE_PROPERTIES_DISCARD_TO_COMPARE); | ||
}); | ||
var stateD3Links = currentState.d3Links.map(function (l) { | ||
return { | ||
source: getId(l.source), | ||
target: getId(l.target) | ||
}; | ||
}); | ||
var graphElementsUpdated = !((0, _utils.isDeepEqual)(nextNodes, stateD3Nodes) && (0, _utils.isDeepEqual)(nextLinks, stateD3Links)); | ||
var newGraphElements = nextNodes.length !== stateD3Nodes.length || nextLinks.length !== stateD3Links.length || !(0, _utils.isDeepEqual)(nextNodes.map(_pickId), stateD3Nodes.map(_pickId)) || !(0, _utils.isDeepEqual)(nextLinks.map(_pickSourceAndTarget), stateD3Links.map(_pickSourceAndTarget)); | ||
return { | ||
graphElementsUpdated: graphElementsUpdated, | ||
newGraphElements: newGraphElements | ||
}; | ||
} | ||
/** | ||
@@ -340,10 +326,13 @@ * Logic to check for changes in graph config. | ||
*/ | ||
function checkForGraphConfigChanges(nextProps, currentState) { | ||
var newConfig = nextProps.config || {}; | ||
var configUpdated = newConfig && !_utils2.default.isEmptyObject(newConfig) && !_utils2.default.isDeepEqual(newConfig, currentState.config); | ||
var d3ConfigUpdated = newConfig && newConfig.d3 && !_utils2.default.isDeepEqual(newConfig.d3, currentState.config.d3); | ||
return { configUpdated: configUpdated, d3ConfigUpdated: d3ConfigUpdated }; | ||
var newConfig = nextProps.config || {}; | ||
var configUpdated = newConfig && !(0, _utils.isEmptyObject)(newConfig) && !(0, _utils.isDeepEqual)(newConfig, currentState.config); | ||
var d3ConfigUpdated = newConfig && newConfig.d3 && !(0, _utils.isDeepEqual)(newConfig.d3, currentState.config.d3); | ||
return { | ||
configUpdated: configUpdated, | ||
d3ConfigUpdated: d3ConfigUpdated | ||
}; | ||
} | ||
/** | ||
@@ -354,18 +343,37 @@ * Returns the transformation to apply in order to center the graph on the | ||
* @param {Object} config - same as {@link #graphrenderer|config in renderGraph}. | ||
* @returns {string} transform rule to apply. | ||
* @returns {string|undefined} transform rule to apply. | ||
* @memberof Graph/helper | ||
*/ | ||
function getCenterAndZoomTransformation(d3Node, config) { | ||
if (!d3Node) { | ||
return; | ||
} | ||
if (!d3Node) { | ||
return; | ||
} | ||
var width = config.width, | ||
height = config.height, | ||
focusZoom = config.focusZoom; | ||
var width = config.width, | ||
height = config.height, | ||
focusZoom = config.focusZoom; | ||
return "\n translate(".concat(width / 2, ", ").concat(height / 2, ")\n scale(").concat(focusZoom, ")\n translate(").concat(-d3Node.x, ", ").concat(-d3Node.y, ")\n "); | ||
} | ||
/** | ||
* This function extracts an id from a link. | ||
* **Why this function?** | ||
* According to [d3-force](https://github.com/d3/d3-force#link_links) | ||
* d3 links might be initialized with "source" and "target" | ||
* properties as numbers or strings, but after initialization they | ||
* are converted to an object. This small utility functions ensures | ||
* that weather in initialization or further into the lifetime of the graph | ||
* we always get the id. | ||
* @param {Object|string|number} sot source or target | ||
* of the link to extract id. | ||
* we want to extract an id. | ||
* @returns {string|number} the id of the link. | ||
* @memberof Graph/helper | ||
*/ | ||
return "\n translate(" + width / 2 + ", " + height / 2 + ")\n scale(" + focusZoom + ")\n translate(" + -d3Node.x + ", " + -d3Node.y + ")\n "; | ||
function getId(sot) { | ||
return sot.id !== undefined && sot.id !== null ? sot.id : sot; | ||
} | ||
/** | ||
@@ -381,67 +389,70 @@ * Encapsulates common procedures to initialize graph. | ||
*/ | ||
function initializeGraphState(_ref, state) { | ||
var data = _ref.data, | ||
id = _ref.id, | ||
config = _ref.config; | ||
var data = _ref.data, | ||
id = _ref.id, | ||
config = _ref.config; | ||
_validateGraphData(data); | ||
_validateGraphData(data); | ||
var graph = void 0; | ||
var graph; | ||
if (state && state.nodes) { | ||
graph = { | ||
nodes: data.nodes.map(function (n) { | ||
return state.nodes[n.id] ? _extends({}, n, _utils2.default.pick(state.nodes[n.id], NODE_PROPS_WHITELIST)) : _extends({}, n); | ||
}), | ||
links: data.links.map(function (l, index) { | ||
return _mergeDataLinkWithD3Link(l, index, state && state.d3Links, config, state); | ||
}) | ||
}; | ||
} else { | ||
graph = { | ||
nodes: data.nodes.map(function (n) { | ||
return _extends({}, n); | ||
}), | ||
links: data.links.map(function (l) { | ||
return _extends({}, l); | ||
}) | ||
}; | ||
} | ||
if (state && state.nodes) { | ||
graph = { | ||
nodes: data.nodes.map(function (n) { | ||
return state.nodes[n.id] ? _objectSpread({}, n, {}, (0, _utils.pick)(state.nodes[n.id], NODE_PROPS_WHITELIST)) : _objectSpread({}, n); | ||
}), | ||
links: data.links.map(function (l, index) { | ||
return _mergeDataLinkWithD3Link(l, index, state && state.d3Links, config, state); | ||
}) | ||
}; | ||
} else { | ||
graph = { | ||
nodes: data.nodes.map(function (n) { | ||
return _objectSpread({}, n); | ||
}), | ||
links: data.links.map(function (l) { | ||
return _objectSpread({}, l); | ||
}) | ||
}; | ||
} | ||
var newConfig = _extends({}, _utils2.default.merge(_graph5.default, config || {})); | ||
var links = _initializeLinks(graph.links, newConfig); // matrix of graph connections | ||
var nodes = _tagOrphanNodes(_initializeNodes(graph.nodes), links); | ||
var _graph = graph, | ||
d3Nodes = _graph.nodes, | ||
d3Links = _graph.links; | ||
var newConfig = _objectSpread({}, (0, _utils.merge)(_graph3["default"], config || {})), | ||
links = _initializeLinks(graph.links, newConfig), | ||
// matrix of graph connections | ||
nodes = _tagOrphanNodes(_initializeNodes(graph.nodes), links); | ||
var formatedId = id.replace(/ /g, "_"); | ||
var simulation = _createForceSimulation(newConfig.width, newConfig.height, newConfig.d3 && newConfig.d3.gravity); | ||
var _graph = graph, | ||
d3Nodes = _graph.nodes, | ||
d3Links = _graph.links; | ||
var formatedId = id.replace(/ /g, "_"); | ||
var minZoom = newConfig.minZoom, | ||
maxZoom = newConfig.maxZoom, | ||
focusZoom = newConfig.focusZoom; | ||
var simulation = _createForceSimulation(newConfig.width, newConfig.height, newConfig.d3 && newConfig.d3.gravity); | ||
var minZoom = newConfig.minZoom, | ||
maxZoom = newConfig.maxZoom, | ||
focusZoom = newConfig.focusZoom; | ||
if (focusZoom > maxZoom) { | ||
newConfig.focusZoom = maxZoom; | ||
} else if (focusZoom < minZoom) { | ||
newConfig.focusZoom = minZoom; | ||
} | ||
if (focusZoom > maxZoom) { | ||
newConfig.focusZoom = maxZoom; | ||
} else if (focusZoom < minZoom) { | ||
newConfig.focusZoom = minZoom; | ||
} | ||
return { | ||
id: formatedId, | ||
config: newConfig, | ||
links: links, | ||
d3Links: d3Links, | ||
nodes: nodes, | ||
d3Nodes: d3Nodes, | ||
highlightedNode: "", | ||
simulation: simulation, | ||
newGraphElements: false, | ||
configUpdated: false, | ||
transform: 1 | ||
}; | ||
return { | ||
id: formatedId, | ||
config: newConfig, | ||
links: links, | ||
d3Links: d3Links, | ||
nodes: nodes, | ||
d3Nodes: d3Nodes, | ||
highlightedNode: "", | ||
simulation: simulation, | ||
newGraphElements: false, | ||
configUpdated: false, | ||
transform: 1, | ||
draggedNode: null | ||
}; | ||
} | ||
/** | ||
@@ -458,28 +469,30 @@ * This function updates the highlighted value for a given node and also updates highlight props. | ||
*/ | ||
function updateNodeHighlightedValue(nodes, links, config, id) { | ||
var value = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; | ||
var value = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; | ||
var highlightedNode = value ? id : ""; | ||
var highlightedNode = value ? id : ""; | ||
var node = _extends({}, nodes[id], { highlighted: value }); | ||
var updatedNodes = _extends({}, nodes, _defineProperty({}, id, node)); | ||
var node = _objectSpread({}, nodes[id], { | ||
highlighted: value | ||
}); | ||
// when highlightDegree is 0 we want only to highlight selected node | ||
if (links[id] && config.highlightDegree !== 0) { | ||
updatedNodes = Object.keys(links[id]).reduce(function (acc, linkId) { | ||
var updatedNode = _extends({}, updatedNodes[linkId], { highlighted: value }); | ||
var updatedNodes = _objectSpread({}, nodes, _defineProperty({}, id, node)); // when highlightDegree is 0 we want only to highlight selected node | ||
return _extends({}, acc, _defineProperty({}, linkId, updatedNode)); | ||
}, updatedNodes); | ||
} | ||
return { | ||
nodes: updatedNodes, | ||
highlightedNode: highlightedNode | ||
}; | ||
} | ||
if (links[id] && config.highlightDegree !== 0) { | ||
updatedNodes = Object.keys(links[id]).reduce(function (acc, linkId) { | ||
var updatedNode = _objectSpread({}, updatedNodes[linkId], { | ||
highlighted: value | ||
}); | ||
exports.checkForGraphConfigChanges = checkForGraphConfigChanges; | ||
exports.checkForGraphElementsChanges = checkForGraphElementsChanges; | ||
exports.getCenterAndZoomTransformation = getCenterAndZoomTransformation; | ||
exports.initializeGraphState = initializeGraphState; | ||
exports.updateNodeHighlightedValue = updateNodeHighlightedValue; | ||
acc[linkId] = updatedNode; | ||
return acc; | ||
}, updatedNodes); | ||
} | ||
return { | ||
nodes: updatedNodes, | ||
highlightedNode: highlightedNode | ||
}; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _react = _interopRequireDefault(require("react")); | ||
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 _d3Drag = require("d3-drag"); | ||
@@ -23,40 +18,44 @@ | ||
var _graph = require("./graph.const"); | ||
var _graph = _interopRequireDefault(require("./graph.const")); | ||
var _graph2 = _interopRequireDefault(_graph); | ||
var _graph2 = _interopRequireDefault(require("./graph.config")); | ||
var _graph3 = require("./graph.config"); | ||
var _err = _interopRequireDefault(require("../../err")); | ||
var _graph4 = _interopRequireDefault(_graph3); | ||
var _collapse = require("./collapse.helper"); | ||
var _err = require("../../err"); | ||
var _graph3 = require("./graph.helper"); | ||
var _err2 = _interopRequireDefault(_err); | ||
var _graph4 = require("./graph.renderer"); | ||
var _collapse = require("./collapse.helper"); | ||
var _utils = require("../../utils"); | ||
var collapseHelper = _interopRequireWildcard(_collapse); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _graph5 = require("./graph.helper"); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var graphHelper = _interopRequireWildcard(_graph5); | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
var _graph6 = require("./graph.renderer"); | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
var graphRenderer = _interopRequireWildcard(_graph6); | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
var _utils = require("../../utils"); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _utils2 = _interopRequireDefault(_utils); | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } | ||
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 _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
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; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
/** | ||
@@ -138,2 +137,7 @@ * Graph component is the main component for react-d3-graph components, its interface allows its user | ||
* | ||
* const onNodePositionChange = function(nodeId, x, y) { | ||
* window.alert(`Node ${nodeId} moved to new position x= ${x} y= ${y}`); | ||
* }; | ||
* | ||
* | ||
* <Graph | ||
@@ -154,521 +158,451 @@ * id='graph-id' // id is mandatory, if no id is defined rd3g will throw an error | ||
*/ | ||
var Graph = function (_React$Component) { | ||
_inherits(Graph, _React$Component); | ||
var Graph = | ||
/*#__PURE__*/ | ||
function (_React$Component) { | ||
_inherits(Graph, _React$Component); | ||
_createClass(Graph, [{ | ||
key: "_graphLinkForceConfig", | ||
_createClass(Graph, [{ | ||
key: "_graphLinkForceConfig", | ||
/** | ||
* Obtain a set of properties which will be used to perform the focus and zoom animation if | ||
* required. In case there's not a focus and zoom animation in progress, it should reset the | ||
* transition duration to zero and clear transformation styles. | ||
* @returns {Object} - Focus and zoom animation properties. | ||
*/ | ||
/** | ||
* This method runs {@link d3-force|https://github.com/d3/d3-force} | ||
* against the current graph. | ||
* @returns {undefined} | ||
*/ | ||
value: function _graphLinkForceConfig() { | ||
var forceLink = (0, _d3Force.forceLink)(this.state.d3Links).id(function (l) { | ||
return l.id; | ||
}).distance(this.state.config.d3.linkLength).strength(this.state.config.d3.linkStrength); | ||
/** | ||
* This method runs {@link d3-force|https://github.com/d3/d3-force} | ||
* against the current graph. | ||
* @returns {undefined} | ||
*/ | ||
value: function _graphLinkForceConfig() { | ||
var forceLink = (0, _d3Force.forceLink)(this.state.d3Links).id(function (l) { | ||
return l.id; | ||
}).distance(this.state.config.d3.linkLength).strength(this.state.config.d3.linkStrength); | ||
this.state.simulation.force(_graph["default"].LINK_CLASS_NAME, forceLink); | ||
} | ||
/** | ||
* This method runs {@link d3-drag|https://github.com/d3/d3-drag} | ||
* against the current graph. | ||
* @returns {undefined} | ||
*/ | ||
this.state.simulation.force(_graph2.default.LINK_CLASS_NAME, forceLink); | ||
} | ||
}, { | ||
key: "_graphNodeDragConfig", | ||
value: function _graphNodeDragConfig() { | ||
var customNodeDrag = (0, _d3Drag.drag)().on("start", this._onDragStart).on("drag", this._onDragMove).on("end", this._onDragEnd); | ||
(0, _d3Selection.select)("#".concat(this.state.id, "-").concat(_graph["default"].GRAPH_WRAPPER_ID)).selectAll(".node").call(customNodeDrag); | ||
} | ||
/** | ||
* Sets d3 tick function and configures other d3 stuff such as forces and drag events. | ||
* Whenever called binds Graph component state with d3. | ||
* @returns {undefined} | ||
*/ | ||
/** | ||
* This method runs {@link d3-drag|https://github.com/d3/d3-drag} | ||
* against the current graph. | ||
* @returns {undefined} | ||
*/ | ||
}, { | ||
key: "_graphBindD3ToReactComponent", | ||
value: function _graphBindD3ToReactComponent() { | ||
this.state.simulation.nodes(this.state.d3Nodes).on("tick", this._tick); | ||
/** | ||
* Obtain a set of properties which will be used to perform the focus and zoom animation if | ||
* required. In case there's not a focus and zoom animation in progress, it should reset the | ||
* transition duration to zero and clear transformation styles. | ||
* @returns {Object} - Focus and zoom animation properties. | ||
*/ | ||
this._graphLinkForceConfig(); | ||
}, { | ||
key: "_graphNodeDragConfig", | ||
value: function _graphNodeDragConfig() { | ||
var customNodeDrag = (0, _d3Drag.drag)().on("start", this._onDragStart).on("drag", this._onDragMove).on("end", this._onDragEnd); | ||
this._graphNodeDragConfig(); | ||
} | ||
/** | ||
* Handles d3 drag 'end' event. | ||
* @returns {undefined} | ||
*/ | ||
(0, _d3Selection.select)("#" + this.state.id + "-" + _graph2.default.GRAPH_WRAPPER_ID).selectAll(".node").call(customNodeDrag); | ||
} | ||
}]); | ||
/** | ||
* Sets d3 tick function and configures other d3 stuff such as forces and drag events. | ||
* Whenever called binds Graph component state with d3. | ||
* @returns {undefined} | ||
*/ | ||
function Graph(props) { | ||
var _this; | ||
}, { | ||
key: "_graphBindD3ToReactComponent", | ||
value: function _graphBindD3ToReactComponent() { | ||
this.state.simulation.nodes(this.state.d3Nodes).on("tick", this._tick); | ||
this._graphLinkForceConfig(); | ||
this._graphNodeDragConfig(); | ||
} | ||
_classCallCheck(this, Graph); | ||
/** | ||
* Handles d3 drag 'end' event. | ||
* @returns {undefined} | ||
*/ | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(Graph).call(this, props)); | ||
_defineProperty(_assertThisInitialized(_this), "_generateFocusAnimationProps", function () { | ||
var focusedNodeId = _this.state.focusedNodeId; // In case an older animation was still not complete, clear previous timeout to ensure the new one is not cancelled | ||
/** | ||
* Handles d3 'drag' event. | ||
* {@link https://github.com/d3/d3-drag/blob/master/README.md#drag_subject|more about d3 drag} | ||
* @param {Object} ev - if not undefined it will contain event data. | ||
* @param {number} index - index of the node that is being dragged. | ||
* @param {Array.<Object>} nodeList - array of d3 nodes. This list of nodes is provided by d3, each | ||
* node contains all information that was previously fed by rd3g. | ||
* @returns {undefined} | ||
*/ | ||
if (_this.state.enableFocusAnimation) { | ||
if (_this.focusAnimationTimeout) { | ||
clearTimeout(_this.focusAnimationTimeout); | ||
} | ||
_this.focusAnimationTimeout = setTimeout(function () { | ||
return _this.setState({ | ||
enableFocusAnimation: false | ||
}); | ||
}, _this.state.config.focusAnimationDuration * 1000); | ||
} | ||
/** | ||
* Handles d3 drag 'start' event. | ||
* @returns {undefined} | ||
*/ | ||
var transitionDuration = _this.state.enableFocusAnimation ? _this.state.config.focusAnimationDuration : 0; | ||
return { | ||
style: { | ||
transitionDuration: "".concat(transitionDuration, "s") | ||
}, | ||
transform: focusedNodeId ? _this.state.focusTransformation : null | ||
}; | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "_onDragEnd", function () { | ||
if (_this.state.draggedNode) { | ||
_this.onNodePositionChange(_this.state.draggedNode); | ||
/** | ||
* Sets nodes and links highlighted value. | ||
* @param {string} id - the id of the node to highlight. | ||
* @param {boolean} [value=false] - the highlight value to be set (true or false). | ||
* @returns {undefined} | ||
*/ | ||
_this._tick({ | ||
draggedNode: null | ||
}); | ||
} | ||
!_this.state.config.staticGraph && _this.state.config.automaticRearrangeAfterDropNode && _this.state.simulation.alphaTarget(_this.state.config.d3.alphaTarget).restart(); | ||
}); | ||
/** | ||
* The tick function simply calls React set state in order to update component and render nodes | ||
* along time as d3 calculates new node positioning. | ||
* @param {Object} state - new state to pass on. | ||
* @param {Function} [cb] - optional callback to fed in to {@link setState()|https://reactjs.org/docs/react-component.html#setstate}. | ||
* @returns {undefined} | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "_onDragMove", function (ev, index, nodeList) { | ||
var id = nodeList[index].id; | ||
if (!_this.state.config.staticGraph) { | ||
// this is where d3 and react bind | ||
var draggedNode = _this.state.nodes[id]; | ||
draggedNode.oldX = draggedNode.x; | ||
draggedNode.oldY = draggedNode.y; | ||
draggedNode.x += _d3Selection.event.dx; | ||
draggedNode.y += _d3Selection.event.dy; // set nodes fixing coords fx and fy | ||
/** | ||
* Configures zoom upon graph with default or user provided values.<br/> | ||
* NOTE: in order for users to be able to double click on nodes, we | ||
* are disabling the native dblclick.zoom from d3 that performs a zoom | ||
* whenever a user double clicks on top of the graph. | ||
* {@link https://github.com/d3/d3-zoom#zoom} | ||
* @returns {undefined} | ||
*/ | ||
draggedNode["fx"] = draggedNode.x; | ||
draggedNode["fy"] = draggedNode.y; | ||
_this._tick({ | ||
draggedNode: draggedNode | ||
}); | ||
} | ||
}); | ||
/** | ||
* Handler for 'zoom' event within zoom config. | ||
* @returns {Object} returns the transformed elements within the svg graph area. | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "_onDragStart", function () { | ||
_this.pauseSimulation(); | ||
if (_this.state.enableFocusAnimation) { | ||
_this.setState({ | ||
enableFocusAnimation: false | ||
}); | ||
} | ||
}); | ||
/** | ||
* Calls the callback passed to the component. | ||
* @param {Object} e - The event of onClick handler. | ||
* @returns {undefined} | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "_setNodeHighlightedValue", function (id) { | ||
var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
return _this._tick((0, _graph3.updateNodeHighlightedValue)(_this.state.nodes, _this.state.links, _this.state.config, id, value)); | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "_tick", function () { | ||
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var cb = arguments.length > 1 ? arguments[1] : undefined; | ||
return cb ? _this.setState(state, cb) : _this.setState(state); | ||
}); | ||
/** | ||
* Collapses the nodes, then checks if the click is doubled and calls the callback passed to the component. | ||
* @param {string} clickedNodeId - The id of the node where the click was performed. | ||
* @returns {undefined} | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "_zoomConfig", function () { | ||
(0, _d3Selection.select)("#".concat(_this.state.id, "-").concat(_graph["default"].GRAPH_WRAPPER_ID)).call((0, _d3Zoom.zoom)().scaleExtent([_this.state.config.minZoom, _this.state.config.maxZoom]).on("zoom", _this._zoomed)).on("dblclick.zoom", null); | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "_zoomed", function () { | ||
var transform = _d3Selection.event.transform; | ||
(0, _d3Selection.selectAll)("#".concat(_this.state.id, "-").concat(_graph["default"].GRAPH_CONTAINER_ID)).attr("transform", transform); | ||
_this.state.config.panAndZoom && _this.setState({ | ||
transform: transform.k | ||
}); | ||
}); | ||
/** | ||
* Handles mouse over node event. | ||
* @param {string} id - id of the node that participates in the event. | ||
* @returns {undefined} | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "onClickGraph", function (e) { | ||
var _e$target, _e$target$attributes, _e$target$attributes$; | ||
if (_this.state.enableFocusAnimation) { | ||
_this.setState({ | ||
enableFocusAnimation: false | ||
}); | ||
} // Only trigger the graph onClickHandler, if not clicked a node or link. | ||
// toUpperCase() is added as a precaution, as the documentation says tagName should always | ||
// return in UPPERCASE, but chrome returns lowercase | ||
/** | ||
* Handles mouse out node event. | ||
* @param {string} id - id of the node that participates in the event. | ||
* @returns {undefined} | ||
*/ | ||
var tagName = e.target && e.target.tagName; | ||
var name = e === null || e === void 0 ? void 0 : (_e$target = e.target) === null || _e$target === void 0 ? void 0 : (_e$target$attributes = _e$target.attributes) === null || _e$target$attributes === void 0 ? void 0 : (_e$target$attributes$ = _e$target$attributes.name) === null || _e$target$attributes$ === void 0 ? void 0 : _e$target$attributes$.value; | ||
var svgContainerName = "svg-container-".concat(_this.state.id); | ||
/** | ||
* Handles mouse over link event. | ||
* @param {string} source - id of the source node that participates in the event. | ||
* @param {string} target - id of the target node that participates in the event. | ||
* @returns {undefined} | ||
*/ | ||
if (tagName.toUpperCase() === "SVG" && name === svgContainerName) { | ||
_this.props.onClickGraph && _this.props.onClickGraph(); | ||
} | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "onClickNode", function (clickedNodeId) { | ||
if (_this.state.config.collapsible) { | ||
var leafConnections = (0, _collapse.getTargetLeafConnections)(clickedNodeId, _this.state.links, _this.state.config); | ||
var links = (0, _collapse.toggleLinksMatrixConnections)(_this.state.links, leafConnections, _this.state.config); | ||
var d3Links = (0, _collapse.toggleLinksConnections)(_this.state.d3Links, links); | ||
var firstLeaf = leafConnections === null || leafConnections === void 0 ? void 0 : leafConnections["0"]; | ||
var isExpanding = false; | ||
/** | ||
* Handles mouse out link event. | ||
* @param {string} source - id of the source node that participates in the event. | ||
* @param {string} target - id of the target node that participates in the event. | ||
* @returns {undefined} | ||
*/ | ||
if (firstLeaf) { | ||
var visibility = links[firstLeaf.source][firstLeaf.target]; | ||
isExpanding = visibility === 1; | ||
} | ||
_this._tick({ | ||
links: links, | ||
d3Links: d3Links | ||
}, function () { | ||
_this.props.onClickNode && _this.props.onClickNode(clickedNodeId); | ||
/** | ||
* Calls d3 simulation.stop().<br/> | ||
* {@link https://github.com/d3/d3-force#simulation_stop} | ||
* @returns {undefined} | ||
*/ | ||
if (isExpanding) { | ||
_this._graphNodeDragConfig(); | ||
} | ||
}); | ||
} else { | ||
if (!_this.nodeClickTimer) { | ||
_this.nodeClickTimer = setTimeout(function () { | ||
_this.props.onClickNode && _this.props.onClickNode(clickedNodeId); | ||
_this.nodeClickTimer = null; | ||
}, _graph["default"].TTL_DOUBLE_CLICK_IN_MS); | ||
} else { | ||
_this.props.onDoubleClickNode && _this.props.onDoubleClickNode(clickedNodeId); | ||
_this.nodeClickTimer = clearTimeout(_this.nodeClickTimer); | ||
} | ||
} | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "onMouseOverNode", function (id) { | ||
_this.props.onMouseOverNode && _this.props.onMouseOverNode(id); | ||
_this.state.config.nodeHighlightBehavior && _this._setNodeHighlightedValue(id, true); | ||
}); | ||
/** | ||
* This method resets all nodes fixed positions by deleting the properties fx (fixed x) | ||
* and fy (fixed y). Following this, a simulation is triggered in order to force nodes to go back | ||
* to their original positions (or at least new positions according to the d3 force parameters). | ||
* @returns {undefined} | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "onMouseOutNode", function (id) { | ||
_this.props.onMouseOutNode && _this.props.onMouseOutNode(id); | ||
_this.state.config.nodeHighlightBehavior && _this._setNodeHighlightedValue(id, false); | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "onMouseOverLink", function (source, target) { | ||
_this.props.onMouseOverLink && _this.props.onMouseOverLink(source, target); | ||
/** | ||
* Calls d3 simulation.restart().<br/> | ||
* {@link https://github.com/d3/d3-force#simulation_restart} | ||
* @returns {undefined} | ||
*/ | ||
}]); | ||
function Graph(props) { | ||
_classCallCheck(this, Graph); | ||
var _this = _possibleConstructorReturn(this, (Graph.__proto__ || Object.getPrototypeOf(Graph)).call(this, props)); | ||
_this._generateFocusAnimationProps = function () { | ||
var focusedNodeId = _this.state.focusedNodeId; | ||
// In case an older animation was still not complete, clear previous timeout to ensure the new one is not cancelled | ||
if (_this.state.enableFocusAnimation) { | ||
if (_this.focusAnimationTimeout) { | ||
clearTimeout(_this.focusAnimationTimeout); | ||
} | ||
_this.focusAnimationTimeout = setTimeout(function () { | ||
return _this.setState({ enableFocusAnimation: false }); | ||
}, _this.state.config.focusAnimationDuration * 1000); | ||
} | ||
var transitionDuration = _this.state.enableFocusAnimation ? _this.state.config.focusAnimationDuration : 0; | ||
return { | ||
style: { transitionDuration: transitionDuration + "s" }, | ||
transform: focusedNodeId ? _this.state.focusTransformation : null | ||
}; | ||
if (_this.state.config.linkHighlightBehavior) { | ||
var highlightedLink = { | ||
source: source, | ||
target: target | ||
}; | ||
_this._onDragEnd = function () { | ||
return !_this.state.config.staticGraph && _this.state.config.automaticRearrangeAfterDropNode && _this.state.simulation.alphaTarget(_this.state.config.d3.alphaTarget).restart(); | ||
}; | ||
_this._tick({ | ||
highlightedLink: highlightedLink | ||
}); | ||
} | ||
}); | ||
_this._onDragMove = function (ev, index, nodeList) { | ||
var id = nodeList[index].id; | ||
_defineProperty(_assertThisInitialized(_this), "onMouseOutLink", function (source, target) { | ||
_this.props.onMouseOutLink && _this.props.onMouseOutLink(source, target); | ||
if (!_this.state.config.staticGraph) { | ||
// this is where d3 and react bind | ||
var draggedNode = _this.state.nodes[id]; | ||
if (_this.state.config.linkHighlightBehavior) { | ||
var highlightedLink = undefined; | ||
draggedNode.x += _d3Selection.event.dx; | ||
draggedNode.y += _d3Selection.event.dy; | ||
_this._tick({ | ||
highlightedLink: highlightedLink | ||
}); | ||
} | ||
}); | ||
// set nodes fixing coords fx and fy | ||
draggedNode["fx"] = draggedNode.x; | ||
draggedNode["fy"] = draggedNode.y; | ||
_defineProperty(_assertThisInitialized(_this), "onNodePositionChange", function (node) { | ||
if (!_this.props.onNodePositionChange) { | ||
return; | ||
} | ||
_this._tick(); | ||
} | ||
}; | ||
var id = node.id, | ||
oldX = node.oldX, | ||
oldY = node.oldY, | ||
x = node.x, | ||
y = node.y; | ||
var deltaX = x - oldX; | ||
var deltaY = y - oldY; | ||
_this._onDragStart = function () { | ||
_this.pauseSimulation(); | ||
if (_this.state.enableFocusAnimation) { | ||
_this.setState({ enableFocusAnimation: false }); | ||
} | ||
}; | ||
if (deltaX !== 0 || deltaY !== 0) { | ||
_this.props.onNodePositionChange(id, x, y); | ||
} | ||
}); | ||
_this._setNodeHighlightedValue = function (id) { | ||
var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
return _this._tick(graphHelper.updateNodeHighlightedValue(_this.state.nodes, _this.state.links, _this.state.config, id, value)); | ||
}; | ||
_defineProperty(_assertThisInitialized(_this), "pauseSimulation", function () { | ||
return _this.state.simulation.stop(); | ||
}); | ||
_this._tick = function () { | ||
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var cb = arguments[1]; | ||
return cb ? _this.setState(state, cb) : _this.setState(state); | ||
}; | ||
_defineProperty(_assertThisInitialized(_this), "resetNodesPositions", function () { | ||
if (!_this.state.config.staticGraph) { | ||
for (var nodeId in _this.state.nodes) { | ||
var node = _this.state.nodes[nodeId]; | ||
_this._zoomConfig = function () { | ||
(0, _d3Selection.select)("#" + _this.state.id + "-" + _graph2.default.GRAPH_WRAPPER_ID).call((0, _d3Zoom.zoom)().scaleExtent([_this.state.config.minZoom, _this.state.config.maxZoom]).on("zoom", _this._zoomed)).on("dblclick.zoom", null); | ||
}; | ||
if (node.fx && node.fy) { | ||
Reflect.deleteProperty(node, "fx"); | ||
Reflect.deleteProperty(node, "fy"); | ||
} | ||
} | ||
_this._zoomed = function () { | ||
var transform = _d3Selection.event.transform; | ||
_this.state.simulation.alphaTarget(_this.state.config.d3.alphaTarget).restart(); | ||
(0, _d3Selection.selectAll)("#" + _this.state.id + "-" + _graph2.default.GRAPH_CONTAINER_ID).attr("transform", transform); | ||
_this._tick(); | ||
} | ||
}); | ||
_this.state.config.panAndZoom && _this.setState({ transform: transform.k }); | ||
}; | ||
_defineProperty(_assertThisInitialized(_this), "restartSimulation", function () { | ||
return !_this.state.config.staticGraph && _this.state.simulation.restart(); | ||
}); | ||
_this.onClickGraph = function (e) { | ||
if (_this.state.enableFocusAnimation) { | ||
_this.setState({ enableFocusAnimation: false }); | ||
} | ||
if (!_this.props.id) { | ||
(0, _utils.throwErr)(_this.constructor.name, _err["default"].GRAPH_NO_ID_PROP); | ||
} | ||
// Only trigger the graph onClickHandler, if not clicked a node or link. | ||
// toUpperCase() is added as a precaution, as the documentation says tagName should always | ||
// return in UPPERCASE, but chrome returns lowercase | ||
var tagName = e.target && e.target.tagName; | ||
var name = e.target && e.target.attributes && e.target.attributes.name && e.target.attributes.name.value; | ||
var svgContainerName = "svg-container-" + _this.state.id; | ||
_this.focusAnimationTimeout = null; | ||
_this.nodeClickTimer = null; | ||
_this.state = (0, _graph3.initializeGraphState)(_this.props, _this.state); | ||
return _this; | ||
} | ||
/** | ||
* @deprecated | ||
* `componentWillReceiveProps` has a replacement method in react v16.3 onwards. | ||
* that is getDerivedStateFromProps. | ||
* But one needs to be aware that if an anti pattern of `componentWillReceiveProps` is | ||
* in place for this implementation the migration might not be that easy. | ||
* See {@link https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html}. | ||
* @param {Object} nextProps - props. | ||
* @returns {undefined} | ||
*/ | ||
// eslint-disable-next-line | ||
if (tagName.toUpperCase() === "SVG" && name === svgContainerName) { | ||
_this.props.onClickGraph && _this.props.onClickGraph(); | ||
} | ||
}; | ||
_this.onClickNode = function (clickedNodeId) { | ||
if (_this.state.config.collapsible) { | ||
var leafConnections = collapseHelper.getTargetLeafConnections(clickedNodeId, _this.state.links, _this.state.config); | ||
var links = collapseHelper.toggleLinksMatrixConnections(_this.state.links, leafConnections, _this.state.config); | ||
var d3Links = collapseHelper.toggleLinksConnections(_this.state.d3Links, links); | ||
var firstLeaf = leafConnections && leafConnections.length && leafConnections[0]; | ||
var isExpanding = false; | ||
_createClass(Graph, [{ | ||
key: "UNSAFE_componentWillReceiveProps", | ||
value: function UNSAFE_componentWillReceiveProps(nextProps) { | ||
var _checkForGraphElement = (0, _graph3.checkForGraphElementsChanges)(nextProps, this.state), | ||
graphElementsUpdated = _checkForGraphElement.graphElementsUpdated, | ||
newGraphElements = _checkForGraphElement.newGraphElements; | ||
if (firstLeaf) { | ||
var visibility = links[firstLeaf.source][firstLeaf.target]; | ||
var state = graphElementsUpdated ? (0, _graph3.initializeGraphState)(nextProps, this.state) : this.state; | ||
var newConfig = nextProps.config || {}; | ||
isExpanding = visibility === 1; | ||
} | ||
var _checkForGraphConfigC = (0, _graph3.checkForGraphConfigChanges)(nextProps, this.state), | ||
configUpdated = _checkForGraphConfigC.configUpdated, | ||
d3ConfigUpdated = _checkForGraphConfigC.d3ConfigUpdated; | ||
_this._tick({ | ||
links: links, | ||
d3Links: d3Links | ||
}, function () { | ||
_this.props.onClickNode && _this.props.onClickNode(clickedNodeId); | ||
var config = configUpdated ? (0, _utils.merge)(_graph2["default"], newConfig) : this.state.config; // in order to properly update graph data we need to pause eventual d3 ongoing animations | ||
if (isExpanding) { | ||
_this._graphNodeDragConfig(); | ||
} | ||
}); | ||
} else { | ||
if (!_this.nodeClickTimer) { | ||
_this.nodeClickTimer = setTimeout(function () { | ||
_this.props.onClickNode && _this.props.onClickNode(clickedNodeId); | ||
_this.nodeClickTimer = null; | ||
}, _graph2.default.TTL_DOUBLE_CLICK_IN_MS); | ||
} else { | ||
_this.props.onDoubleClickNode && _this.props.onDoubleClickNode(clickedNodeId); | ||
_this.nodeClickTimer = clearTimeout(_this.nodeClickTimer); | ||
} | ||
} | ||
}; | ||
newGraphElements && this.pauseSimulation(); | ||
var transform = newConfig.panAndZoom !== this.state.config.panAndZoom ? 1 : this.state.transform; | ||
var focusedNodeId = nextProps.data.focusedNodeId; | ||
var d3FocusedNode = this.state.d3Nodes.find(function (node) { | ||
return "".concat(node.id) === "".concat(focusedNodeId); | ||
}); | ||
var focusTransformation = (0, _graph3.getCenterAndZoomTransformation)(d3FocusedNode, this.state.config); | ||
var enableFocusAnimation = this.props.data.focusedNodeId !== nextProps.data.focusedNodeId; | ||
this.setState(_objectSpread({}, state, { | ||
config: config, | ||
configUpdated: configUpdated, | ||
d3ConfigUpdated: d3ConfigUpdated, | ||
newGraphElements: newGraphElements, | ||
transform: transform, | ||
focusedNodeId: focusedNodeId, | ||
enableFocusAnimation: enableFocusAnimation, | ||
focusTransformation: focusTransformation | ||
})); | ||
} | ||
}, { | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate() { | ||
// if the property staticGraph was activated we want to stop possible ongoing simulation | ||
var shouldPause = this.state.config.staticGraph || this.state.config.staticGraphWithDragAndDrop; | ||
_this.onMouseOverNode = function (id) { | ||
_this.props.onMouseOverNode && _this.props.onMouseOverNode(id); | ||
if (shouldPause) { | ||
this.pauseSimulation(); | ||
} | ||
_this.state.config.nodeHighlightBehavior && _this._setNodeHighlightedValue(id, true); | ||
}; | ||
if (!this.state.config.staticGraph && (this.state.newGraphElements || this.state.d3ConfigUpdated)) { | ||
this._graphBindD3ToReactComponent(); | ||
_this.onMouseOutNode = function (id) { | ||
_this.props.onMouseOutNode && _this.props.onMouseOutNode(id); | ||
if (!this.state.config.staticGraphWithDragAndDrop) { | ||
this.restartSimulation(); | ||
} | ||
_this.state.config.nodeHighlightBehavior && _this._setNodeHighlightedValue(id, false); | ||
}; | ||
this.setState({ | ||
newGraphElements: false, | ||
d3ConfigUpdated: false | ||
}); | ||
} else if (this.state.configUpdated) { | ||
this._graphNodeDragConfig(); | ||
} | ||
_this.onMouseOverLink = function (source, target) { | ||
_this.props.onMouseOverLink && _this.props.onMouseOverLink(source, target); | ||
if (this.state.configUpdated) { | ||
this._zoomConfig(); | ||
if (_this.state.config.linkHighlightBehavior) { | ||
var highlightedLink = { source: source, target: target }; | ||
this.setState({ | ||
configUpdated: false | ||
}); | ||
} | ||
} | ||
}, { | ||
key: "componentDidMount", | ||
value: function componentDidMount() { | ||
if (!this.state.config.staticGraph) { | ||
this._graphBindD3ToReactComponent(); | ||
} // graph zoom and drag&drop all network | ||
_this._tick({ highlightedLink: highlightedLink }); | ||
} | ||
}; | ||
_this.onMouseOutLink = function (source, target) { | ||
_this.props.onMouseOutLink && _this.props.onMouseOutLink(source, target); | ||
this._zoomConfig(); | ||
} | ||
}, { | ||
key: "componentWillUnmount", | ||
value: function componentWillUnmount() { | ||
this.pauseSimulation(); | ||
if (_this.state.config.linkHighlightBehavior) { | ||
var highlightedLink = undefined; | ||
if (this.nodeClickTimer) { | ||
clearTimeout(this.nodeClickTimer); | ||
this.nodeClickTimer = null; | ||
} | ||
_this._tick({ highlightedLink: highlightedLink }); | ||
} | ||
}; | ||
if (this.focusAnimationTimeout) { | ||
clearTimeout(this.focusAnimationTimeout); | ||
this.focusAnimationTimeout = null; | ||
} | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _renderGraph = (0, _graph4.renderGraph)(this.state.nodes, { | ||
onClickNode: this.onClickNode, | ||
onDoubleClickNode: this.onDoubleClickNode, | ||
onRightClickNode: this.props.onRightClickNode, | ||
onMouseOverNode: this.onMouseOverNode, | ||
onMouseOut: this.onMouseOutNode | ||
}, this.state.d3Links, this.state.links, { | ||
onClickLink: this.props.onClickLink, | ||
onRightClickLink: this.props.onRightClickLink, | ||
onMouseOverLink: this.onMouseOverLink, | ||
onMouseOutLink: this.onMouseOutLink | ||
}, this.state.config, this.state.highlightedNode, this.state.highlightedLink, this.state.transform), | ||
nodes = _renderGraph.nodes, | ||
links = _renderGraph.links, | ||
defs = _renderGraph.defs; | ||
_this.pauseSimulation = function () { | ||
return _this.state.simulation.stop(); | ||
}; | ||
var svgStyle = { | ||
height: this.state.config.height, | ||
width: this.state.config.width | ||
}; | ||
_this.resetNodesPositions = function () { | ||
if (!_this.state.config.staticGraph) { | ||
for (var nodeId in _this.state.nodes) { | ||
var node = _this.state.nodes[nodeId]; | ||
var containerProps = this._generateFocusAnimationProps(); | ||
if (node.fx && node.fy) { | ||
Reflect.deleteProperty(node, "fx"); | ||
Reflect.deleteProperty(node, "fy"); | ||
} | ||
} | ||
_this.state.simulation.alphaTarget(_this.state.config.d3.alphaTarget).restart(); | ||
_this._tick(); | ||
} | ||
}; | ||
_this.restartSimulation = function () { | ||
return !_this.state.config.staticGraph && _this.state.simulation.restart(); | ||
}; | ||
if (!_this.props.id) { | ||
_utils2.default.throwErr(_this.constructor.name, _err2.default.GRAPH_NO_ID_PROP); | ||
} | ||
_this.focusAnimationTimeout = null; | ||
_this.state = graphHelper.initializeGraphState(_this.props, _this.state); | ||
return _this; | ||
return _react["default"].createElement("div", { | ||
id: "".concat(this.state.id, "-").concat(_graph["default"].GRAPH_WRAPPER_ID) | ||
}, _react["default"].createElement("svg", { | ||
name: "svg-container-".concat(this.state.id), | ||
style: svgStyle, | ||
onClick: this.onClickGraph | ||
}, defs, _react["default"].createElement("g", _extends({ | ||
id: "".concat(this.state.id, "-").concat(_graph["default"].GRAPH_CONTAINER_ID) | ||
}, containerProps), links, nodes))); | ||
} | ||
}]); | ||
/** | ||
* @deprecated | ||
* `componentWillReceiveProps` has a replacement method in react v16.3 onwards. | ||
* that is getDerivedStateFromProps. | ||
* But one needs to be aware that if an anti pattern of `componentWillReceiveProps` is | ||
* in place for this implementation the migration might not be that easy. | ||
* See {@link https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html}. | ||
* @param {Object} nextProps - props. | ||
* @returns {undefined} | ||
*/ | ||
// eslint-disable-next-line | ||
return Graph; | ||
}(_react["default"].Component); | ||
_createClass(Graph, [{ | ||
key: "UNSAFE_componentWillReceiveProps", | ||
value: function UNSAFE_componentWillReceiveProps(nextProps) { | ||
var _graphHelper$checkFor = graphHelper.checkForGraphElementsChanges(nextProps, this.state), | ||
graphElementsUpdated = _graphHelper$checkFor.graphElementsUpdated, | ||
newGraphElements = _graphHelper$checkFor.newGraphElements; | ||
var state = graphElementsUpdated ? graphHelper.initializeGraphState(nextProps, this.state) : this.state; | ||
var newConfig = nextProps.config || {}; | ||
var _graphHelper$checkFor2 = graphHelper.checkForGraphConfigChanges(nextProps, this.state), | ||
configUpdated = _graphHelper$checkFor2.configUpdated, | ||
d3ConfigUpdated = _graphHelper$checkFor2.d3ConfigUpdated; | ||
var config = configUpdated ? _utils2.default.merge(_graph4.default, newConfig) : this.state.config; | ||
// in order to properly update graph data we need to pause eventual d3 ongoing animations | ||
newGraphElements && this.pauseSimulation(); | ||
var transform = newConfig.panAndZoom !== this.state.config.panAndZoom ? 1 : this.state.transform; | ||
var focusedNodeId = nextProps.data.focusedNodeId; | ||
var d3FocusedNode = this.state.d3Nodes.find(function (node) { | ||
return "" + node.id === "" + focusedNodeId; | ||
}); | ||
var focusTransformation = graphHelper.getCenterAndZoomTransformation(d3FocusedNode, this.state.config); | ||
var enableFocusAnimation = this.props.data.focusedNodeId !== nextProps.data.focusedNodeId; | ||
this.setState(_extends({}, state, { | ||
config: config, | ||
configUpdated: configUpdated, | ||
d3ConfigUpdated: d3ConfigUpdated, | ||
newGraphElements: newGraphElements, | ||
transform: transform, | ||
focusedNodeId: focusedNodeId, | ||
enableFocusAnimation: enableFocusAnimation, | ||
focusTransformation: focusTransformation | ||
})); | ||
} | ||
}, { | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate() { | ||
// if the property staticGraph was activated we want to stop possible ongoing simulation | ||
var shouldPause = this.state.config.staticGraph || this.state.config.staticGraphWithDragAndDrop; | ||
if (shouldPause) { | ||
this.pauseSimulation(); | ||
} | ||
if (!this.state.config.staticGraph && (this.state.newGraphElements || this.state.d3ConfigUpdated)) { | ||
this._graphBindD3ToReactComponent(); | ||
if (!this.state.config.staticGraphWithDragAndDrop) { | ||
this.restartSimulation(); | ||
} | ||
this.setState({ newGraphElements: false, d3ConfigUpdated: false }); | ||
} else if (this.state.configUpdated) { | ||
this._graphNodeDragConfig(); | ||
} | ||
if (this.state.configUpdated) { | ||
this._zoomConfig(); | ||
this.setState({ configUpdated: false }); | ||
} | ||
} | ||
}, { | ||
key: "componentDidMount", | ||
value: function componentDidMount() { | ||
if (!this.state.config.staticGraph) { | ||
this._graphBindD3ToReactComponent(); | ||
} | ||
// graph zoom and drag&drop all network | ||
this._zoomConfig(); | ||
} | ||
}, { | ||
key: "componentWillUnmount", | ||
value: function componentWillUnmount() { | ||
this.pauseSimulation(); | ||
this.nodeClickTimer && clearTimeout(this.nodeClickTimer); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
var _graphRenderer$render = graphRenderer.renderGraph(this.state.nodes, { | ||
onClickNode: this.onClickNode, | ||
onDoubleClickNode: this.onDoubleClickNode, | ||
onRightClickNode: this.props.onRightClickNode, | ||
onMouseOverNode: this.onMouseOverNode, | ||
onMouseOut: this.onMouseOutNode | ||
}, this.state.d3Links, this.state.links, { | ||
onClickLink: this.props.onClickLink, | ||
onRightClickLink: this.props.onRightClickLink, | ||
onMouseOverLink: this.onMouseOverLink, | ||
onMouseOutLink: this.onMouseOutLink | ||
}, this.state.config, this.state.highlightedNode, this.state.highlightedLink, this.state.transform), | ||
nodes = _graphRenderer$render.nodes, | ||
links = _graphRenderer$render.links, | ||
defs = _graphRenderer$render.defs; | ||
var svgStyle = { | ||
height: this.state.config.height, | ||
width: this.state.config.width | ||
}; | ||
var containerProps = this._generateFocusAnimationProps(); | ||
return _react2.default.createElement( | ||
"div", | ||
{ id: this.state.id + "-" + _graph2.default.GRAPH_WRAPPER_ID }, | ||
_react2.default.createElement( | ||
"svg", | ||
{ name: "svg-container-" + this.state.id, style: svgStyle, onClick: this.onClickGraph }, | ||
defs, | ||
_react2.default.createElement( | ||
"g", | ||
_extends({ id: this.state.id + "-" + _graph2.default.GRAPH_CONTAINER_ID }, containerProps), | ||
links, | ||
nodes | ||
) | ||
) | ||
); | ||
} | ||
}]); | ||
return Graph; | ||
}(_react2.default.Component); | ||
exports.default = Graph; | ||
exports["default"] = Graph; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.renderGraph = undefined; | ||
exports.renderGraph = renderGraph; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** | ||
* @module Graph/renderer | ||
* @description | ||
* Offers a series of methods that isolate render logic for Graph component. | ||
*/ | ||
var _react = _interopRequireDefault(require("react")); | ||
var _graph = _interopRequireDefault(require("./graph.const")); | ||
var _react = require("react"); | ||
var _marker = require("../marker/marker.const"); | ||
var _react2 = _interopRequireDefault(_react); | ||
var _Link = _interopRequireDefault(require("../link/Link")); | ||
var _graph = require("./graph.const"); | ||
var _Node = _interopRequireDefault(require("../node/Node")); | ||
var _graph2 = _interopRequireDefault(_graph); | ||
var _Marker = _interopRequireDefault(require("../marker/Marker")); | ||
var _marker = require("../marker/marker.const"); | ||
var _graph2 = require("./graph.builder"); | ||
var _Link = require("../link/Link"); | ||
var _graph3 = require("../graph/graph.helper"); | ||
var _Link2 = _interopRequireDefault(_Link); | ||
var _collapse = require("./collapse.helper"); | ||
var _Node = require("../node/Node"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _Node2 = _interopRequireDefault(_Node); | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
var _Marker = require("../marker/Marker"); | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
var _Marker2 = _interopRequireDefault(_Marker); | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
var _graph3 = require("./graph.builder"); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
var _collapse = require("./collapse.helper"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
@@ -57,25 +50,27 @@ * Build Link components given a list of links. | ||
function _renderLinks(nodes, links, linksMatrix, config, linkCallbacks, highlightedNode, highlightedLink, transform) { | ||
var outLinks = links; | ||
var outLinks = links; | ||
if (config.collapsible) { | ||
outLinks = outLinks.filter(function (_ref) { | ||
var isHidden = _ref.isHidden; | ||
return !isHidden; | ||
}); | ||
} | ||
if (config.collapsible) { | ||
outLinks = outLinks.filter(function (_ref) { | ||
var isHidden = _ref.isHidden; | ||
return !isHidden; | ||
}); | ||
} | ||
return outLinks.map(function (link) { | ||
var source = link.source, | ||
target = link.target; | ||
// FIXME: solve this source data inconsistency later | ||
var sourceId = source.id !== undefined && source.id !== null ? source.id : source; | ||
var targetId = target.id !== undefined && target.id !== null ? target.id : target; | ||
var key = "" + sourceId + _graph2.default.COORDS_SEPARATOR + targetId; | ||
var props = (0, _graph3.buildLinkProps)(_extends({}, link, { source: "" + sourceId, target: "" + targetId }), nodes, linksMatrix, config, linkCallbacks, "" + highlightedNode, highlightedLink, transform); | ||
return _react2.default.createElement(_Link2.default, _extends({ key: key, id: key }, props)); | ||
}); | ||
return outLinks.map(function (link) { | ||
var source = link.source, | ||
target = link.target; | ||
var sourceId = (0, _graph3.getId)(source); | ||
var targetId = (0, _graph3.getId)(target); | ||
var key = "".concat(sourceId).concat(_graph["default"].COORDS_SEPARATOR).concat(targetId); | ||
var props = (0, _graph2.buildLinkProps)(_objectSpread({}, link, { | ||
source: "".concat(sourceId), | ||
target: "".concat(targetId) | ||
}), nodes, linksMatrix, config, linkCallbacks, "".concat(highlightedNode), highlightedLink, transform); | ||
return _react["default"].createElement(_Link["default"], _extends({ | ||
key: key, | ||
id: key | ||
}, props)); | ||
}); | ||
} | ||
/** | ||
@@ -95,18 +90,22 @@ * Function that builds Node components. | ||
*/ | ||
function _renderNodes(nodes, nodeCallbacks, config, highlightedNode, highlightedLink, transform, linksMatrix) { | ||
var outNodes = Object.keys(nodes); | ||
if (config.collapsible) { | ||
outNodes = outNodes.filter(function (nodeId) { | ||
return (0, _collapse.isNodeVisible)(nodeId, nodes, linksMatrix); | ||
}); | ||
} | ||
return outNodes.map(function (nodeId) { | ||
var props = (0, _graph3.buildNodeProps)(_extends({}, nodes[nodeId], { id: "" + nodeId }), config, nodeCallbacks, highlightedNode, highlightedLink, transform); | ||
function _renderNodes(nodes, nodeCallbacks, config, highlightedNode, highlightedLink, transform, linksMatrix) { | ||
var outNodes = Object.keys(nodes); | ||
return _react2.default.createElement(_Node2.default, _extends({ key: nodeId }, props)); | ||
if (config.collapsible) { | ||
outNodes = outNodes.filter(function (nodeId) { | ||
return (0, _collapse.isNodeVisible)(nodeId, nodes, linksMatrix); | ||
}); | ||
} | ||
return outNodes.map(function (nodeId) { | ||
var props = (0, _graph2.buildNodeProps)(_objectSpread({}, nodes[nodeId], { | ||
id: "".concat(nodeId) | ||
}), config, nodeCallbacks, highlightedNode, highlightedLink, transform); | ||
return _react["default"].createElement(_Node["default"], _extends({ | ||
key: nodeId | ||
}, props)); | ||
}); | ||
} | ||
/** | ||
@@ -119,29 +118,42 @@ * Builds graph defs (for now markers, but we could also have gradients for instance). | ||
*/ | ||
function _renderDefs() { | ||
var cachedDefs = void 0; | ||
return function (config) { | ||
if (cachedDefs) { | ||
return cachedDefs; | ||
} | ||
var small = _marker.MARKER_SMALL_SIZE; | ||
var medium = small + _marker.MARKER_MEDIUM_OFFSET * config.maxZoom / 3; | ||
var large = small + _marker.MARKER_LARGE_OFFSET * config.maxZoom / 3; | ||
function _renderDefs() { | ||
var cachedDefs; | ||
return function (config) { | ||
if (cachedDefs) { | ||
return cachedDefs; | ||
} | ||
cachedDefs = _react2.default.createElement( | ||
"defs", | ||
null, | ||
_react2.default.createElement(_Marker2.default, { id: _marker.MARKERS.MARKER_S, refX: small, fill: config.link.color }), | ||
_react2.default.createElement(_Marker2.default, { id: _marker.MARKERS.MARKER_SH, refX: small, fill: config.link.highlightColor }), | ||
_react2.default.createElement(_Marker2.default, { id: _marker.MARKERS.MARKER_M, refX: medium, fill: config.link.color }), | ||
_react2.default.createElement(_Marker2.default, { id: _marker.MARKERS.MARKER_MH, refX: medium, fill: config.link.highlightColor }), | ||
_react2.default.createElement(_Marker2.default, { id: _marker.MARKERS.MARKER_L, refX: large, fill: config.link.color }), | ||
_react2.default.createElement(_Marker2.default, { id: _marker.MARKERS.MARKER_LH, refX: large, fill: config.link.highlightColor }) | ||
); | ||
return cachedDefs; | ||
}; | ||
var small = _marker.MARKER_SMALL_SIZE; | ||
var medium = small + _marker.MARKER_MEDIUM_OFFSET * config.maxZoom / 3; | ||
var large = small + _marker.MARKER_LARGE_OFFSET * config.maxZoom / 3; | ||
cachedDefs = _react["default"].createElement("defs", null, _react["default"].createElement(_Marker["default"], { | ||
id: _marker.MARKERS.MARKER_S, | ||
refX: small, | ||
fill: config.link.color | ||
}), _react["default"].createElement(_Marker["default"], { | ||
id: _marker.MARKERS.MARKER_SH, | ||
refX: small, | ||
fill: config.link.highlightColor | ||
}), _react["default"].createElement(_Marker["default"], { | ||
id: _marker.MARKERS.MARKER_M, | ||
refX: medium, | ||
fill: config.link.color | ||
}), _react["default"].createElement(_Marker["default"], { | ||
id: _marker.MARKERS.MARKER_MH, | ||
refX: medium, | ||
fill: config.link.highlightColor | ||
}), _react["default"].createElement(_Marker["default"], { | ||
id: _marker.MARKERS.MARKER_L, | ||
refX: large, | ||
fill: config.link.color | ||
}), _react["default"].createElement(_Marker["default"], { | ||
id: _marker.MARKERS.MARKER_LH, | ||
refX: large, | ||
fill: config.link.highlightColor | ||
})); | ||
return cachedDefs; | ||
}; | ||
} | ||
/** | ||
@@ -153,4 +165,5 @@ * Memoized reference for _renderDefs. | ||
*/ | ||
var _memoizedRenderDefs = _renderDefs(); | ||
/** | ||
@@ -197,10 +210,10 @@ * Method that actually is exported an consumed by Graph component in order to build all Nodes and Link | ||
*/ | ||
function renderGraph(nodes, nodeCallbacks, links, linksMatrix, linkCallbacks, config, highlightedNode, highlightedLink, transform) { | ||
return { | ||
nodes: _renderNodes(nodes, nodeCallbacks, config, highlightedNode, highlightedLink, transform, linksMatrix), | ||
links: _renderLinks(nodes, links, linksMatrix, config, linkCallbacks, highlightedNode, highlightedLink, transform), | ||
defs: _memoizedRenderDefs(config) | ||
}; | ||
} | ||
exports.renderGraph = renderGraph; | ||
return { | ||
nodes: _renderNodes(nodes, nodeCallbacks, config, highlightedNode, highlightedLink, transform, linksMatrix), | ||
links: _renderLinks(nodes, links, linksMatrix, config, linkCallbacks, highlightedNode, highlightedLink, transform), | ||
defs: _memoizedRenderDefs(config) | ||
}; | ||
} |
@@ -6,2 +6,4 @@ "use strict"; | ||
}); | ||
exports.LINE_TYPES = void 0; | ||
/** | ||
@@ -12,2 +14,3 @@ * @module Link/const | ||
*/ | ||
/** | ||
@@ -25,3 +28,2 @@ * @typedef {Object} LINE_TYPES | ||
}; | ||
exports.LINE_TYPES = LINE_TYPES; |
@@ -6,14 +6,9 @@ "use strict"; | ||
}); | ||
exports.buildLinkPathDefinition = undefined; | ||
exports.buildLinkPathDefinition = buildLinkPathDefinition; | ||
var _RADIUS_STRATEGIES; | ||
var _link = require("./link.const"); | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /** | ||
* @module Link/helper | ||
* @description | ||
* A set of helper methods to manipulate/create links. | ||
*/ | ||
var _RADIUS_STRATEGIES; | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -28,3 +23,2 @@ /** | ||
} | ||
/** | ||
@@ -39,9 +33,9 @@ * Computes radius for a smooth curve effect. | ||
*/ | ||
function smoothCurveRadius(x1, y1, x2, y2) { | ||
var dx = x2 - x1; | ||
var dy = y2 - y1; | ||
return Math.sqrt(dx * dx + dy * dy); | ||
} | ||
/** | ||
@@ -52,2 +46,4 @@ * Computes radius value for a full curve (semi circumference). | ||
*/ | ||
function fullCurveRadius() { | ||
@@ -58,3 +54,2 @@ return 1; | ||
var RADIUS_STRATEGIES = (_RADIUS_STRATEGIES = {}, _defineProperty(_RADIUS_STRATEGIES, _link.LINE_TYPES.STRAIGHT, straightLineRadius), _defineProperty(_RADIUS_STRATEGIES, _link.LINE_TYPES.CURVE_SMOOTH, smoothCurveRadius), _defineProperty(_RADIUS_STRATEGIES, _link.LINE_TYPES.CURVE_FULL, fullCurveRadius), _RADIUS_STRATEGIES); | ||
/** | ||
@@ -68,6 +63,6 @@ * Get a strategy to compute line radius.<br/> | ||
*/ | ||
function getRadiusStrategy(type) { | ||
return RADIUS_STRATEGIES[type] || RADIUS_STRATEGIES[_link.LINE_TYPES.STRAIGHT]; | ||
} | ||
/** | ||
@@ -84,7 +79,9 @@ * This method returns the path definition for a given link base on the line type | ||
*/ | ||
function buildLinkPathDefinition(_ref) { | ||
var _ref$source = _ref.source, | ||
source = _ref$source === undefined ? {} : _ref$source, | ||
source = _ref$source === void 0 ? {} : _ref$source, | ||
_ref$target = _ref.target, | ||
target = _ref$target === undefined ? {} : _ref$target; | ||
target = _ref$target === void 0 ? {} : _ref$target; | ||
var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _link.LINE_TYPES.STRAIGHT; | ||
@@ -95,9 +92,5 @@ var sx = source.x, | ||
ty = target.y; | ||
var validType = _link.LINE_TYPES[type] || _link.LINE_TYPES.STRAIGHT; | ||
var radius = getRadiusStrategy(validType)(sx, sy, tx, ty); | ||
return "M" + sx + "," + sy + "A" + radius + "," + radius + " 0 0,1 " + tx + "," + ty; | ||
} | ||
exports.buildLinkPathDefinition = buildLinkPathDefinition; | ||
return "M".concat(sx, ",").concat(sy, "A").concat(radius, ",").concat(radius, " 0 0,1 ").concat(tx, ",").concat(ty); | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _react = _interopRequireDefault(require("react")); | ||
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; }; }(); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _react = require("react"); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _react2 = _interopRequireDefault(_react); | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
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 _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); } } | ||
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; } | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
/** | ||
@@ -57,109 +68,90 @@ * Link component is responsible for encapsulating link render. | ||
*/ | ||
var Link = function (_React$Component) { | ||
_inherits(Link, _React$Component); | ||
var Link = | ||
/*#__PURE__*/ | ||
function (_React$Component) { | ||
_inherits(Link, _React$Component); | ||
function Link() { | ||
var _ref; | ||
function Link() { | ||
var _getPrototypeOf2; | ||
var _temp, _this, _ret; | ||
var _this; | ||
_classCallCheck(this, Link); | ||
_classCallCheck(this, Link); | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Link.__proto__ || Object.getPrototypeOf(Link)).call.apply(_ref, [this].concat(args))), _this), _this.handleOnClickLink = function () { | ||
return _this.props.onClickLink && _this.props.onClickLink(_this.props.source, _this.props.target); | ||
}, _this.handleOnRightClickLink = function (event) { | ||
return _this.props.onRightClickLink && _this.props.onRightClickLink(event, _this.props.source, _this.props.target); | ||
}, _this.handleOnMouseOverLink = function () { | ||
return _this.props.onMouseOverLink && _this.props.onMouseOverLink(_this.props.source, _this.props.target); | ||
}, _this.handleOnMouseOutLink = function () { | ||
return _this.props.onMouseOutLink && _this.props.onMouseOutLink(_this.props.source, _this.props.target); | ||
}, _temp), _possibleConstructorReturn(_this, _ret); | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
/** | ||
* Handle link click event. | ||
* @returns {undefined} | ||
*/ | ||
_this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(Link)).call.apply(_getPrototypeOf2, [this].concat(args))); | ||
/** | ||
* Handle link right click event. | ||
* @param {Object} event - native event. | ||
* @returns {undefined} | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "handleOnClickLink", function () { | ||
return _this.props.onClickLink && _this.props.onClickLink(_this.props.source, _this.props.target); | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "handleOnRightClickLink", function (event) { | ||
return _this.props.onRightClickLink && _this.props.onRightClickLink(event, _this.props.source, _this.props.target); | ||
}); | ||
/** | ||
* Handle mouse over link event. | ||
* @returns {undefined} | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "handleOnMouseOverLink", function () { | ||
return _this.props.onMouseOverLink && _this.props.onMouseOverLink(_this.props.source, _this.props.target); | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "handleOnMouseOutLink", function () { | ||
return _this.props.onMouseOutLink && _this.props.onMouseOutLink(_this.props.source, _this.props.target); | ||
}); | ||
/** | ||
* Handle mouse out link event. | ||
* @returns {undefined} | ||
*/ | ||
return _this; | ||
} | ||
_createClass(Link, [{ | ||
key: "render", | ||
value: function render() { | ||
var lineStyle = { | ||
strokeWidth: this.props.strokeWidth, | ||
stroke: this.props.stroke, | ||
opacity: this.props.opacity, | ||
fill: "none", | ||
cursor: this.props.mouseCursor | ||
}; | ||
var lineProps = { | ||
className: this.props.className, | ||
d: this.props.d, | ||
onClick: this.handleOnClickLink, | ||
onContextMenu: this.handleOnRightClickLink, | ||
onMouseOut: this.handleOnMouseOutLink, | ||
onMouseOver: this.handleOnMouseOverLink, | ||
style: lineStyle | ||
}; | ||
_createClass(Link, [{ | ||
key: "render", | ||
value: function render() { | ||
var lineStyle = { | ||
strokeWidth: this.props.strokeWidth, | ||
stroke: this.props.stroke, | ||
opacity: this.props.opacity, | ||
fill: "none", | ||
cursor: this.props.mouseCursor | ||
}; | ||
if (this.props.markerId) { | ||
lineProps.markerEnd = "url(#".concat(this.props.markerId, ")"); | ||
} | ||
var lineProps = { | ||
className: this.props.className, | ||
d: this.props.d, | ||
onClick: this.handleOnClickLink, | ||
onContextMenu: this.handleOnRightClickLink, | ||
onMouseOut: this.handleOnMouseOutLink, | ||
onMouseOver: this.handleOnMouseOverLink, | ||
style: lineStyle | ||
}; | ||
if (this.props.markerId) { | ||
lineProps.markerEnd = "url(#" + this.props.markerId + ")"; | ||
} | ||
var _props = this.props, | ||
label = _props.label, | ||
id = _props.id; | ||
var textProps = { | ||
dy: -1, | ||
style: { | ||
fill: this.props.fontColor, | ||
fontSize: this.props.fontSize, | ||
fontWeight: this.props.fontWeight | ||
} | ||
}; | ||
return _react2.default.createElement( | ||
"g", | ||
null, | ||
_react2.default.createElement("path", _extends({}, lineProps, { id: id })), | ||
label && _react2.default.createElement( | ||
"text", | ||
_extends({ style: { textAnchor: "middle" } }, textProps), | ||
_react2.default.createElement( | ||
"textPath", | ||
{ href: "#" + id, startOffset: "50%" }, | ||
label | ||
) | ||
) | ||
); | ||
var _this$props = this.props, | ||
label = _this$props.label, | ||
id = _this$props.id; | ||
var textProps = { | ||
dy: -1, | ||
style: { | ||
fill: this.props.fontColor, | ||
fontSize: this.props.fontSize, | ||
fontWeight: this.props.fontWeight | ||
} | ||
}]); | ||
}; | ||
return _react["default"].createElement("g", null, _react["default"].createElement("path", _extends({}, lineProps, { | ||
id: id | ||
})), label && _react["default"].createElement("text", _extends({ | ||
style: { | ||
textAnchor: "middle" | ||
} | ||
}, textProps), _react["default"].createElement("textPath", { | ||
href: "#".concat(id), | ||
startOffset: "50%" | ||
}, label))); | ||
} | ||
}]); | ||
return Link; | ||
}(_react2.default.Component); | ||
return Link; | ||
}(_react["default"].Component); | ||
exports.default = Link; | ||
exports["default"] = Link; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.SIZES = exports.MARKERS = exports.MARKER_SMALL_SIZE = exports.MARKER_MEDIUM_OFFSET = exports.MARKER_LARGE_OFFSET = exports.HIGHLIGHTED = void 0; | ||
var HIGHLIGHTED = "H"; | ||
exports.HIGHLIGHTED = HIGHLIGHTED; | ||
var MARKER_SMALL_SIZE = 16; | ||
exports.MARKER_SMALL_SIZE = MARKER_SMALL_SIZE; | ||
var MARKER_MEDIUM_OFFSET = 2; | ||
var MARKER_LARGE_OFFSET = 4; | ||
// internal marker flavors for cross referencing | ||
exports.MARKER_MEDIUM_OFFSET = MARKER_MEDIUM_OFFSET; | ||
var MARKER_LARGE_OFFSET = 4; // internal marker flavors for cross referencing | ||
exports.MARKER_LARGE_OFFSET = MARKER_LARGE_OFFSET; | ||
var MARKERS = { | ||
MARKER_S: "marker-small", | ||
MARKER_SH: "marker-small-highlighted", | ||
MARKER_M: "marker-medium", | ||
MARKER_MH: "marker-medium-highlighted", | ||
MARKER_L: "marker-large", | ||
MARKER_LH: "marker-large-highlighted" | ||
}; | ||
// hard coded aggregation of the different sizes available for markers | ||
MARKER_S: "marker-small", | ||
MARKER_SH: "marker-small-highlighted", | ||
MARKER_M: "marker-medium", | ||
MARKER_MH: "marker-medium-highlighted", | ||
MARKER_L: "marker-large", | ||
MARKER_LH: "marker-large-highlighted" | ||
}; // hard coded aggregation of the different sizes available for markers | ||
exports.MARKERS = MARKERS; | ||
var SIZES = { | ||
S: "S", | ||
M: "M", | ||
L: "L" | ||
S: "S", | ||
M: "M", | ||
L: "L" | ||
}; | ||
exports.HIGHLIGHTED = HIGHLIGHTED; | ||
exports.MARKER_LARGE_OFFSET = MARKER_LARGE_OFFSET; | ||
exports.MARKER_MEDIUM_OFFSET = MARKER_MEDIUM_OFFSET; | ||
exports.MARKER_SMALL_SIZE = MARKER_SMALL_SIZE; | ||
exports.MARKERS = MARKERS; | ||
exports.SIZES = SIZES; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.getMarkerId = undefined; | ||
exports.getMarkerId = void 0; | ||
@@ -11,4 +11,9 @@ var _marker = require("./marker.const"); | ||
/** | ||
* @module Marker/helper | ||
* @description | ||
* Offers a series of methods to compute proper markers within a given context. | ||
*/ | ||
/** | ||
* This function is a key template builder to access MARKERS structure. | ||
* WARN: function tightly coupled to the MARKERS object in marker.const. | ||
* @param {string} size - string that indicates size of marker. | ||
@@ -20,5 +25,4 @@ * @param {string} highlighted - string that indicates highlight state of marker. | ||
function _markerKeyBuilder(size, highlighted) { | ||
return "MARKER_" + size + highlighted; | ||
return "MARKER_".concat(size).concat(highlighted); | ||
} | ||
/** | ||
@@ -33,17 +37,13 @@ * This functions returns the proper marker size given the inputs that describe the scenario | ||
*/ | ||
/** | ||
* @module Marker/helper | ||
* @description | ||
* Offers a series of methods to compute proper markers within a given context. | ||
*/ | ||
function _getMarkerSize(transform, mMax, lMax) { | ||
if (transform < mMax) { | ||
return _marker.SIZES.S; | ||
} else if (transform >= mMax && transform < lMax) { | ||
return _marker.SIZES.M; | ||
} else { | ||
return _marker.SIZES.L; | ||
} | ||
if (transform < mMax) { | ||
return _marker.SIZES.S; | ||
} else if (transform >= mMax && transform < lMax) { | ||
return _marker.SIZES.M; | ||
} else { | ||
return _marker.SIZES.L; | ||
} | ||
} | ||
/** | ||
@@ -58,14 +58,17 @@ * This function holds logic to retrieve the appropriate marker id that reflects the input | ||
*/ | ||
function _computeMarkerId(highlight, transform, _ref) { | ||
var maxZoom = _ref.maxZoom; | ||
var maxZoom = _ref.maxZoom; | ||
var mMax = maxZoom / 4; | ||
var lMax = maxZoom / 2; | ||
var mMax = maxZoom / 4; | ||
var lMax = maxZoom / 2; | ||
var size = _getMarkerSize(transform, mMax, lMax); | ||
var highlighted = highlight ? _marker.HIGHLIGHTED : ""; | ||
var markerKey = _markerKeyBuilder(size, highlighted); | ||
var size = _getMarkerSize(transform, mMax, lMax); | ||
return _marker.MARKERS[markerKey]; | ||
var highlighted = highlight ? _marker.HIGHLIGHTED : ""; | ||
var markerKey = _markerKeyBuilder(size, highlighted); | ||
return _marker.MARKERS[markerKey]; | ||
} | ||
/** | ||
@@ -79,22 +82,22 @@ * This function memoize results for _computeMarkerId | ||
*/ | ||
function _memoizedComputeMarkerId() { | ||
var cache = {}; | ||
return function (highlight, transform, _ref2) { | ||
var maxZoom = _ref2.maxZoom; | ||
var cacheKey = highlight + ";" + transform + ";" + maxZoom; | ||
function _memoizedComputeMarkerId() { | ||
var cache = {}; | ||
return function (highlight, transform, _ref2) { | ||
var maxZoom = _ref2.maxZoom; | ||
var cacheKey = "".concat(highlight, ";").concat(transform, ";").concat(maxZoom); | ||
if (cache[cacheKey]) { | ||
return cache[cacheKey]; | ||
} | ||
if (cache[cacheKey]) { | ||
return cache[cacheKey]; | ||
} | ||
var markerId = _computeMarkerId(highlight, transform, { maxZoom: maxZoom }); | ||
var markerId = _computeMarkerId(highlight, transform, { | ||
maxZoom: maxZoom | ||
}); | ||
cache[cacheKey] = markerId; | ||
return markerId; | ||
}; | ||
cache[cacheKey] = markerId; | ||
return markerId; | ||
}; | ||
} | ||
/** | ||
@@ -111,4 +114,6 @@ * Memoized reference for _memoizedComputeMarkerId exposed | ||
*/ | ||
var getMarkerId = _memoizedComputeMarkerId(); | ||
exports.getMarkerId = getMarkerId; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
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 = _interopRequireDefault(require("react")); | ||
var _react = require("react"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _react2 = _interopRequireDefault(_react); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
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 _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); } } | ||
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; } | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
/** | ||
@@ -27,37 +36,36 @@ * Market component provides configurable interface to marker definition. | ||
*/ | ||
var Marker = function (_React$Component) { | ||
_inherits(Marker, _React$Component); | ||
var Marker = | ||
/*#__PURE__*/ | ||
function (_React$Component) { | ||
_inherits(Marker, _React$Component); | ||
function Marker() { | ||
_classCallCheck(this, Marker); | ||
function Marker() { | ||
_classCallCheck(this, Marker); | ||
return _possibleConstructorReturn(this, (Marker.__proto__ || Object.getPrototypeOf(Marker)).apply(this, arguments)); | ||
return _possibleConstructorReturn(this, _getPrototypeOf(Marker).apply(this, arguments)); | ||
} | ||
_createClass(Marker, [{ | ||
key: "render", | ||
// TODO: make Marker configurable in the future (markerWidth, markerHeight) | ||
value: function render() { | ||
return _react["default"].createElement("marker", { | ||
className: "marker", | ||
id: this.props.id, | ||
viewBox: "0 -5 10 10", | ||
refX: this.props.refX, | ||
refY: "0", | ||
markerWidth: "6", | ||
markerHeight: "6", | ||
orient: "auto", | ||
fill: this.props.fill | ||
}, _react["default"].createElement("path", { | ||
d: "M0,-5L10,0L0,5" | ||
})); | ||
} | ||
}]); | ||
_createClass(Marker, [{ | ||
key: "render", | ||
return Marker; | ||
}(_react["default"].Component); | ||
// TODO: make Marker configurable in the future (markerWidth, markerHeight) | ||
value: function render() { | ||
return _react2.default.createElement( | ||
"marker", | ||
{ | ||
className: "marker", | ||
id: this.props.id, | ||
viewBox: "0 -5 10 10", | ||
refX: this.props.refX, | ||
refY: "0", | ||
markerWidth: "6", | ||
markerHeight: "6", | ||
orient: "auto", | ||
fill: this.props.fill | ||
}, | ||
_react2.default.createElement("path", { d: "M0,-5L10,0L0,5" }) | ||
); | ||
} | ||
}]); | ||
return Marker; | ||
}(_react2.default.Component); | ||
exports.default = Marker; | ||
exports["default"] = Marker; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _graph = _interopRequireDefault(require("../graph/graph.config")); | ||
var _graph = require("../graph/graph.config"); | ||
var _const = _interopRequireDefault(require("../../const")); | ||
var _graph2 = _interopRequireDefault(_graph); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _const = require("../../const"); | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
var _const2 = _interopRequireDefault(_const); | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
exports.default = _extends({ | ||
ARC: { | ||
START_ANGLE: 0, | ||
END_ANGLE: 2 * Math.PI | ||
}, | ||
DEFAULT_NODE_SIZE: _graph2.default.node.size, | ||
NODE_LABEL_DX: ".90em", | ||
NODE_LABEL_DY: ".35em" | ||
}, _const2.default); | ||
var _default = _objectSpread({ | ||
ARC: { | ||
START_ANGLE: 0, | ||
END_ANGLE: 2 * Math.PI | ||
}, | ||
DEFAULT_NODE_SIZE: _graph["default"].node.size, | ||
NODE_LABEL_DX: ".90em", | ||
NODE_LABEL_DY: ".35em" | ||
}, _const["default"]); | ||
exports["default"] = _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
var _d3Shape = require("d3-shape"); | ||
var _node = require("./node.const"); | ||
var _node = _interopRequireDefault(require("./node.const")); | ||
var _node2 = _interopRequireDefault(_node); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* @module Node/helper | ||
* @description | ||
* Some methods that help no the process of rendering a node. | ||
*/ | ||
@@ -23,28 +28,29 @@ /** | ||
*/ | ||
/** | ||
* @module Node/helper | ||
* @description | ||
* Some methods that help no the process of rendering a node. | ||
*/ | ||
function _convertTypeToD3Symbol(typeName) { | ||
switch (typeName) { | ||
case _node2.default.SYMBOLS.CIRCLE: | ||
return _d3Shape.symbolCircle; | ||
case _node2.default.SYMBOLS.CROSS: | ||
return _d3Shape.symbolCross; | ||
case _node2.default.SYMBOLS.DIAMOND: | ||
return _d3Shape.symbolDiamond; | ||
case _node2.default.SYMBOLS.SQUARE: | ||
return _d3Shape.symbolSquare; | ||
case _node2.default.SYMBOLS.STAR: | ||
return _d3Shape.symbolStar; | ||
case _node2.default.SYMBOLS.TRIANGLE: | ||
return _d3Shape.symbolTriangle; | ||
case _node2.default.SYMBOLS.WYE: | ||
return _d3Shape.symbolWye; | ||
default: | ||
return _d3Shape.symbolCircle; | ||
} | ||
switch (typeName) { | ||
case _node["default"].SYMBOLS.CIRCLE: | ||
return _d3Shape.symbolCircle; | ||
case _node["default"].SYMBOLS.CROSS: | ||
return _d3Shape.symbolCross; | ||
case _node["default"].SYMBOLS.DIAMOND: | ||
return _d3Shape.symbolDiamond; | ||
case _node["default"].SYMBOLS.SQUARE: | ||
return _d3Shape.symbolSquare; | ||
case _node["default"].SYMBOLS.STAR: | ||
return _d3Shape.symbolStar; | ||
case _node["default"].SYMBOLS.TRIANGLE: | ||
return _d3Shape.symbolTriangle; | ||
case _node["default"].SYMBOLS.WYE: | ||
return _d3Shape.symbolWye; | ||
default: | ||
return _d3Shape.symbolCircle; | ||
} | ||
} | ||
/** | ||
@@ -58,15 +64,17 @@ * Build a d3 svg symbol based on passed symbol and symbol type. | ||
*/ | ||
function buildSvgSymbol() { | ||
var size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _node2.default.DEFAULT_NODE_SIZE; | ||
var symbolTypeDesc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _node2.default.SYMBOLS.CIRCLE; | ||
return (0, _d3Shape.symbol)().size(function () { | ||
return size; | ||
}).type(function () { | ||
return _convertTypeToD3Symbol(symbolTypeDesc); | ||
})(); | ||
var size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _node["default"].DEFAULT_NODE_SIZE; | ||
var symbolTypeDesc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _node["default"].SYMBOLS.CIRCLE; | ||
return (0, _d3Shape.symbol)().size(function () { | ||
return size; | ||
}).type(function () { | ||
return _convertTypeToD3Symbol(symbolTypeDesc); | ||
})(); | ||
} | ||
exports.default = { | ||
buildSvgSymbol: buildSvgSymbol | ||
}; | ||
var _default = { | ||
buildSvgSymbol: buildSvgSymbol | ||
}; | ||
exports["default"] = _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _react = _interopRequireDefault(require("react")); | ||
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 _node = _interopRequireDefault(require("./node.const")); | ||
var _react = require("react"); | ||
var _node2 = _interopRequireDefault(require("./node.helper")); | ||
var _react2 = _interopRequireDefault(_react); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _node = require("./node.const"); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _node2 = _interopRequireDefault(_node); | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
var _node3 = require("./node.helper"); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _node4 = _interopRequireDefault(_node3); | ||
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); } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
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 _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
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; } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
/** | ||
@@ -74,147 +81,124 @@ * Node component is responsible for encapsulating node render. | ||
*/ | ||
var Node = function (_React$Component) { | ||
_inherits(Node, _React$Component); | ||
var Node = | ||
/*#__PURE__*/ | ||
function (_React$Component) { | ||
_inherits(Node, _React$Component); | ||
function Node() { | ||
var _ref; | ||
function Node() { | ||
var _getPrototypeOf2; | ||
var _temp, _this, _ret; | ||
var _this; | ||
_classCallCheck(this, Node); | ||
_classCallCheck(this, Node); | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = Node.__proto__ || Object.getPrototypeOf(Node)).call.apply(_ref, [this].concat(args))), _this), _this.handleOnClickNode = function () { | ||
return _this.props.onClickNode && _this.props.onClickNode(_this.props.id); | ||
}, _this.handleOnRightClickNode = function (event) { | ||
return _this.props.onRightClickNode && _this.props.onRightClickNode(event, _this.props.id); | ||
}, _this.handleOnMouseOverNode = function () { | ||
return _this.props.onMouseOverNode && _this.props.onMouseOverNode(_this.props.id); | ||
}, _this.handleOnMouseOutNode = function () { | ||
return _this.props.onMouseOut && _this.props.onMouseOut(_this.props.id); | ||
}, _temp), _possibleConstructorReturn(_this, _ret); | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
/** | ||
* Handle click on the node. | ||
* @returns {undefined} | ||
*/ | ||
_this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(Node)).call.apply(_getPrototypeOf2, [this].concat(args))); | ||
/** | ||
* Handle right click on the node. | ||
* @param {Object} event - native event. | ||
* @returns {undefined} | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "handleOnClickNode", function () { | ||
return _this.props.onClickNode && _this.props.onClickNode(_this.props.id); | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "handleOnRightClickNode", function (event) { | ||
return _this.props.onRightClickNode && _this.props.onRightClickNode(event, _this.props.id); | ||
}); | ||
/** | ||
* Handle mouse over node event. | ||
* @returns {undefined} | ||
*/ | ||
_defineProperty(_assertThisInitialized(_this), "handleOnMouseOverNode", function () { | ||
return _this.props.onMouseOverNode && _this.props.onMouseOverNode(_this.props.id); | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "handleOnMouseOutNode", function () { | ||
return _this.props.onMouseOut && _this.props.onMouseOut(_this.props.id); | ||
}); | ||
/** | ||
* Handle mouse out node event. | ||
* @returns {undefined} | ||
*/ | ||
return _this; | ||
} | ||
_createClass(Node, [{ | ||
key: "render", | ||
value: function render() { | ||
var nodeProps = { | ||
cursor: this.props.cursor, | ||
onClick: this.handleOnClickNode, | ||
onContextMenu: this.handleOnRightClickNode, | ||
onMouseOut: this.handleOnMouseOutNode, | ||
onMouseOver: this.handleOnMouseOverNode, | ||
opacity: this.props.opacity | ||
}; | ||
var textProps = { | ||
dx: this.props.dx || _node["default"].NODE_LABEL_DX, | ||
dy: _node["default"].NODE_LABEL_DY, | ||
fill: this.props.fontColor, | ||
fontSize: this.props.fontSize, | ||
fontWeight: this.props.fontWeight, | ||
opacity: this.props.opacity | ||
}; | ||
var size = this.props.size; | ||
var gtx = this.props.cx, | ||
gty = this.props.cy, | ||
label = null, | ||
node = null; | ||
_createClass(Node, [{ | ||
key: "render", | ||
value: function render() { | ||
var nodeProps = { | ||
cursor: this.props.cursor, | ||
onClick: this.handleOnClickNode, | ||
onContextMenu: this.handleOnRightClickNode, | ||
onMouseOut: this.handleOnMouseOutNode, | ||
onMouseOver: this.handleOnMouseOverNode, | ||
opacity: this.props.opacity | ||
}; | ||
if (this.props.svg || this.props.viewGenerator) { | ||
var height = size / 10; | ||
var width = size / 10; | ||
var tx = width / 2; | ||
var ty = height / 2; | ||
var transform = "translate(".concat(tx, ",").concat(ty, ")"); | ||
label = _react["default"].createElement("text", _extends({}, textProps, { | ||
transform: transform | ||
}), this.props.label); // By default, if a view generator is set, it takes precedence over any svg image url | ||
var textProps = { | ||
dx: this.props.dx || _node2.default.NODE_LABEL_DX, | ||
dy: _node2.default.NODE_LABEL_DY, | ||
fill: this.props.fontColor, | ||
fontSize: this.props.fontSize, | ||
fontWeight: this.props.fontWeight, | ||
opacity: this.props.opacity | ||
}; | ||
if (this.props.viewGenerator && !this.props.overrideGlobalViewGenerator) { | ||
node = _react["default"].createElement("svg", _extends({}, nodeProps, { | ||
width: width, | ||
height: height | ||
}), _react["default"].createElement("foreignObject", { | ||
x: "0", | ||
y: "0", | ||
width: "100%", | ||
height: "100%" | ||
}, _react["default"].createElement("section", { | ||
style: { | ||
height: height, | ||
width: width, | ||
backgroundColor: "transparent" | ||
} | ||
}, this.props.viewGenerator(this.props)))); | ||
} else { | ||
node = _react["default"].createElement("image", _extends({}, nodeProps, { | ||
href: this.props.svg, | ||
width: width, | ||
height: height | ||
})); | ||
} // svg offset transform regarding svg width/height | ||
var size = this.props.size; | ||
var gtx = this.props.cx; | ||
var gty = this.props.cy; | ||
var label = void 0; | ||
var node = void 0; | ||
if (this.props.svg || this.props.viewGenerator) { | ||
var height = size / 10; | ||
var width = size / 10; | ||
var tx = width / 2; | ||
var ty = height / 2; | ||
var transform = "translate(" + tx + "," + ty + ")"; | ||
gtx -= tx; | ||
gty -= ty; | ||
} else { | ||
nodeProps.d = _node2["default"].buildSvgSymbol(size, this.props.type); | ||
nodeProps.fill = this.props.fill; | ||
nodeProps.stroke = this.props.stroke; | ||
nodeProps.strokeWidth = this.props.strokeWidth; | ||
label = _react["default"].createElement("text", textProps, this.props.label); | ||
node = _react["default"].createElement("path", nodeProps); | ||
} | ||
label = _react2.default.createElement( | ||
"text", | ||
_extends({}, textProps, { transform: transform }), | ||
this.props.label | ||
); | ||
var gProps = { | ||
className: this.props.className, | ||
cx: this.props.cx, | ||
cy: this.props.cy, | ||
id: this.props.id, | ||
transform: "translate(".concat(gtx, ",").concat(gty, ")") | ||
}; | ||
return _react["default"].createElement("g", gProps, node, this.props.renderLabel && label); | ||
} | ||
}]); | ||
// By default, if a view generator is set, it takes precedence over any svg image url | ||
if (this.props.viewGenerator && !this.props.overrideGlobalViewGenerator) { | ||
node = _react2.default.createElement( | ||
"svg", | ||
_extends({}, nodeProps, { width: width, height: height }), | ||
_react2.default.createElement( | ||
"foreignObject", | ||
{ x: "0", y: "0", width: "100%", height: "100%" }, | ||
_react2.default.createElement( | ||
"section", | ||
{ style: { height: height, width: width, backgroundColor: "transparent" } }, | ||
this.props.viewGenerator(this.props) | ||
) | ||
) | ||
); | ||
} else { | ||
node = _react2.default.createElement("image", _extends({}, nodeProps, { href: this.props.svg, width: width, height: height })); | ||
} | ||
return Node; | ||
}(_react["default"].Component); | ||
// svg offset transform regarding svg width/height | ||
gtx -= tx; | ||
gty -= ty; | ||
} else { | ||
nodeProps.d = _node4.default.buildSvgSymbol(size, this.props.type); | ||
nodeProps.fill = this.props.fill; | ||
nodeProps.stroke = this.props.stroke; | ||
nodeProps.strokeWidth = this.props.strokeWidth; | ||
label = _react2.default.createElement( | ||
"text", | ||
textProps, | ||
this.props.label | ||
); | ||
node = _react2.default.createElement("path", nodeProps); | ||
} | ||
var gProps = { | ||
className: this.props.className, | ||
cx: this.props.cx, | ||
cy: this.props.cy, | ||
id: this.props.id, | ||
transform: "translate(" + gtx + "," + gty + ")" | ||
}; | ||
return _react2.default.createElement( | ||
"g", | ||
gProps, | ||
node, | ||
this.props.renderLabel && label | ||
); | ||
} | ||
}]); | ||
return Node; | ||
}(_react2.default.Component); | ||
exports.default = Node; | ||
exports["default"] = Node; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
/** | ||
@@ -11,12 +13,13 @@ * @ignore | ||
*/ | ||
exports.default = { | ||
SYMBOLS: { | ||
CIRCLE: "circle", | ||
CROSS: "cross", | ||
DIAMOND: "diamond", | ||
SQUARE: "square", | ||
STAR: "star", | ||
TRIANGLE: "triangle", | ||
WYE: "wye" | ||
} | ||
}; | ||
var _default = { | ||
SYMBOLS: { | ||
CIRCLE: "circle", | ||
CROSS: "cross", | ||
DIAMOND: "diamond", | ||
SQUARE: "square", | ||
STAR: "star", | ||
TRIANGLE: "triangle", | ||
WYE: "wye" | ||
} | ||
}; | ||
exports["default"] = _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports["default"] = void 0; | ||
/*eslint max-len: ["error", 200]*/ | ||
exports.default = { | ||
GRAPH_NO_ID_PROP: "id prop not defined! id property is mandatory and it should be unique.", | ||
INVALID_LINKS: "you provided a invalid links data structure. Links source and target attributes must point to an existent node", | ||
INSUFFICIENT_DATA: "you have not provided enough data for react-d3-graph to render something. You need to provide at least one node", | ||
INVALID_LINK_VALUE: "links 'value' attribute must be of type number" | ||
}; | ||
var _default = { | ||
GRAPH_NO_ID_PROP: "id prop not defined! id property is mandatory and it should be unique.", | ||
INVALID_LINKS: "you provided a invalid links data structure. Links source and target attributes must point to an existent node", | ||
INSUFFICIENT_DATA: "you have not provided enough data for react-d3-graph to render something. You need to provide at least one node", | ||
INVALID_LINK_VALUE: "links 'value' attribute must be of type number" | ||
}; | ||
exports["default"] = _default; |
@@ -6,20 +6,27 @@ "use strict"; | ||
}); | ||
exports.Link = exports.Node = exports.Graph = undefined; | ||
Object.defineProperty(exports, "Graph", { | ||
enumerable: true, | ||
get: function get() { | ||
return _Graph["default"]; | ||
} | ||
}); | ||
Object.defineProperty(exports, "Node", { | ||
enumerable: true, | ||
get: function get() { | ||
return _Node["default"]; | ||
} | ||
}); | ||
Object.defineProperty(exports, "Link", { | ||
enumerable: true, | ||
get: function get() { | ||
return _Link["default"]; | ||
} | ||
}); | ||
var _Graph = require("./components/graph/Graph"); | ||
var _Graph = _interopRequireDefault(require("./components/graph/Graph")); | ||
var _Graph2 = _interopRequireDefault(_Graph); | ||
var _Node = _interopRequireDefault(require("./components/node/Node")); | ||
var _Node = require("./components/node/Node"); | ||
var _Link = _interopRequireDefault(require("./components/link/Link")); | ||
var _Node2 = _interopRequireDefault(_Node); | ||
var _Link = require("./components/link/Link"); | ||
var _Link2 = _interopRequireDefault(_Link); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
exports.Graph = _Graph2.default; | ||
exports.Node = _Node2.default; | ||
exports.Link = _Link2.default; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } |
249
lib/utils.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
exports.isDeepEqual = isDeepEqual; | ||
exports.isEmptyObject = isEmptyObject; | ||
exports.deepClone = deepClone; | ||
exports.merge = merge; | ||
exports.pick = pick; | ||
exports.antiPick = antiPick; | ||
exports.throwErr = throwErr; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
@@ -15,7 +22,5 @@ /** | ||
*/ | ||
// This variable assures that recursive methods such as merge and isDeepEqual do not fall on | ||
// circular JSON structure evaluation. | ||
var MAX_DEPTH = 20; | ||
/** | ||
@@ -28,6 +33,6 @@ * Checks whether a certain object property is from object type and is a non empty object. | ||
*/ | ||
function _isPropertyNestedObject(o, k) { | ||
return !!o && o.hasOwnProperty(k) && _typeof(o[k]) === "object" && o[k] !== null && !isEmptyObject(o[k]); | ||
return !!o && Object.prototype.hasOwnProperty.call(o, k) && _typeof(o[k]) === "object" && o[k] !== null && !isEmptyObject(o[k]); | ||
} | ||
/** | ||
@@ -41,62 +46,43 @@ * Generic deep comparison between javascript simple or complex objects. | ||
*/ | ||
function isDeepEqual(o1, o2) { | ||
var _depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; | ||
var diffs = []; | ||
if (_depth === 0 && o1 === o2) { | ||
return true; | ||
} | ||
function isDeepEqual(o1, o2) { | ||
var _depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; | ||
if (isEmptyObject(o1) && !isEmptyObject(o2) || !isEmptyObject(o1) && isEmptyObject(o2)) { | ||
return false; | ||
} | ||
var diffs = []; | ||
var o1Keys = Object.keys(o1); | ||
var o2Keys = Object.keys(o2); | ||
if (_depth === 0 && o1 === o2) { | ||
return true; | ||
} | ||
if (o1Keys.length !== o2Keys.length) { | ||
return false; | ||
} | ||
if (isEmptyObject(o1) && !isEmptyObject(o2) || !isEmptyObject(o1) && isEmptyObject(o2)) { | ||
return false; | ||
} | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
var o1Keys = Object.keys(o1); | ||
var o2Keys = Object.keys(o2); | ||
try { | ||
for (var _iterator = o1Keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var k = _step.value; | ||
if (o1Keys.length !== o2Keys.length) { | ||
return false; | ||
} | ||
var nestedO = _isPropertyNestedObject(o1, k) && _isPropertyNestedObject(o2, k); | ||
for (var _i = 0, _o1Keys = o1Keys; _i < _o1Keys.length; _i++) { | ||
var k = _o1Keys[_i]; | ||
if (nestedO && _depth < MAX_DEPTH) { | ||
diffs.push(isDeepEqual(o1[k], o2[k], _depth + 1)); | ||
} else { | ||
var r = isEmptyObject(o1[k]) && isEmptyObject(o2[k]) || o2.hasOwnProperty(k) && o2[k] === o1[k]; | ||
var nestedO = _isPropertyNestedObject(o1, k) && _isPropertyNestedObject(o2, k); | ||
diffs.push(r); | ||
if (nestedO && _depth < MAX_DEPTH) { | ||
diffs.push(isDeepEqual(o1[k], o2[k], _depth + 1)); | ||
} else { | ||
var r = isEmptyObject(o1[k]) && isEmptyObject(o2[k]) || Object.prototype.hasOwnProperty.call(o2, k) && o2[k] === o1[k]; | ||
diffs.push(r); | ||
if (!r) { | ||
break; | ||
} | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
if (!r) { | ||
break; | ||
} | ||
} | ||
} | ||
return diffs.indexOf(false) === -1; | ||
return diffs.indexOf(false) === -1; | ||
} | ||
/** | ||
@@ -109,6 +95,7 @@ * Checks whether or not a certain object is empty. | ||
*/ | ||
function isEmptyObject(o) { | ||
return !!o && (typeof o === "undefined" ? "undefined" : _typeof(o)) === "object" && !Object.keys(o).length; | ||
return !!o && _typeof(o) === "object" && !Object.keys(o).length; | ||
} | ||
/** | ||
@@ -123,41 +110,21 @@ * Function to deep clone plain javascript objects. | ||
*/ | ||
function deepClone(o) { | ||
var _clone = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var _clone = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var _depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; | ||
var _depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; | ||
// TODO: Handle invalid input o is null, undefined, empty object | ||
var oKeys = Object.keys(o); | ||
var oKeys = Object.keys(o); | ||
// TODO: handle arrays | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
for (var _i2 = 0, _oKeys = oKeys; _i2 < _oKeys.length; _i2++) { | ||
var k = _oKeys[_i2]; | ||
try { | ||
for (var _iterator2 = oKeys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var k = _step2.value; | ||
var nested = _isPropertyNestedObject(o, k); | ||
var nested = _isPropertyNestedObject(o, k); | ||
_clone[k] = nested && _depth < MAX_DEPTH ? deepClone(o[k], {}, _depth + 1) : o[k]; | ||
} | ||
_clone[k] = nested && _depth < MAX_DEPTH ? deepClone(o[k], {}, _depth + 1) : o[k]; | ||
} | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
} | ||
return _clone; | ||
return _clone; | ||
} | ||
/** | ||
@@ -173,54 +140,34 @@ * This function merges two objects o1 and o2, where o2 properties override existent o1 properties, and | ||
*/ | ||
function merge() { | ||
var o1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var o2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var _depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; | ||
var o = {}; | ||
function merge() { | ||
var o1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var o2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
if (Object.keys(o1 || {}).length === 0) { | ||
return o2 && !isEmptyObject(o2) ? o2 : {}; | ||
} | ||
var _depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; | ||
var _iteratorNormalCompletion3 = true; | ||
var _didIteratorError3 = false; | ||
var _iteratorError3 = undefined; | ||
var o = {}; | ||
try { | ||
for (var _iterator3 = Object.keys(o1)[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { | ||
var k = _step3.value; | ||
if (Object.keys(o1 || {}).length === 0) { | ||
return o2 && !isEmptyObject(o2) ? o2 : {}; | ||
} | ||
var nestedO = !!(o2[k] && _typeof(o2[k]) === "object" && _typeof(o1[k]) === "object" && _depth < MAX_DEPTH); | ||
for (var _i3 = 0, _Object$keys = Object.keys(o1); _i3 < _Object$keys.length; _i3++) { | ||
var k = _Object$keys[_i3]; | ||
var nestedO = !!(o2[k] && _typeof(o2[k]) === "object" && _typeof(o1[k]) === "object" && _depth < MAX_DEPTH); | ||
if (nestedO) { | ||
(function () { | ||
var r = merge(o1[k], o2[k], _depth + 1); | ||
o[k] = o1[k].hasOwnProperty("length") && o2[k].hasOwnProperty("length") ? Object.keys(r).map(function (rk) { | ||
return r[rk]; | ||
}) : r; | ||
})(); | ||
} else { | ||
o[k] = o2.hasOwnProperty(k) ? o2[k] : o1[k]; | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError3 = true; | ||
_iteratorError3 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion3 && _iterator3.return) { | ||
_iterator3.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError3) { | ||
throw _iteratorError3; | ||
} | ||
} | ||
if (nestedO) { | ||
(function () { | ||
var r = merge(o1[k], o2[k], _depth + 1); | ||
o[k] = Object.prototype.hasOwnProperty.call(o1[k], "length") && Object.prototype.hasOwnProperty.call(o2[k], "length") ? Object.keys(r).map(function (rk) { | ||
return r[rk]; | ||
}) : r; | ||
})(); | ||
} else { | ||
o[k] = Object.prototype.hasOwnProperty.call(o2, k) ? o2[k] : o1[k]; | ||
} | ||
} | ||
return o; | ||
return o; | ||
} | ||
/** | ||
@@ -234,14 +181,14 @@ * Create new object from the inputted one only with the props passed | ||
*/ | ||
function pick(o) { | ||
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
return props.reduce(function (acc, k) { | ||
if (Object.prototype.hasOwnProperty.call(o, k)) { | ||
acc[k] = o[k]; | ||
} | ||
return props.reduce(function (acc, k) { | ||
if (o.hasOwnProperty(k)) { | ||
acc[k] = o[k]; | ||
} | ||
return acc; | ||
}, {}); | ||
return acc; | ||
}, {}); | ||
} | ||
/** | ||
@@ -254,12 +201,11 @@ * Picks all props except the ones passed in the props array. | ||
*/ | ||
function antiPick(o) { | ||
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var wanted = Object.keys(o).filter(function (k) { | ||
return !props.includes(k); | ||
}); | ||
return pick(o, wanted); | ||
function antiPick(o) { | ||
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; | ||
var wanted = Object.keys(o).filter(function (k) { | ||
return !props.includes(k); | ||
}); | ||
return pick(o, wanted); | ||
} | ||
/** | ||
@@ -272,16 +218,7 @@ * Helper function for customized error logging. | ||
*/ | ||
function throwErr(component, msg) { | ||
var error = "react-d3-graph :: " + component + " :: " + msg; | ||
throw Error(error); | ||
} | ||
exports.default = { | ||
isDeepEqual: isDeepEqual, | ||
isEmptyObject: isEmptyObject, | ||
deepClone: deepClone, | ||
merge: merge, | ||
pick: pick, | ||
antiPick: antiPick, | ||
throwErr: throwErr | ||
}; | ||
function throwErr(component, msg) { | ||
var error = "react-d3-graph :: ".concat(component, " :: ").concat(msg); | ||
throw Error(error); | ||
} |
214
package.json
{ | ||
"name": "react-d3-graph", | ||
"version": "2.2.0", | ||
"description": "React component to build interactive and configurable graphs with d3 effortlessly", | ||
"author": "Daniel Caldas", | ||
"license": "MIT", | ||
"scripts": { | ||
"check": "npm run docs:lint && npm run lint && npm run test && npm run functional", | ||
"check:light": "npm run lint && npm run test", | ||
"dev": "cross-env NODE_ENV=dev webpack-dev-server --mode=development --content-base sandbox --config webpack.config.js --inline --hot --port 3002", | ||
"dist:rd3g": "rm -rf dist/ && webpack --config webpack.config.dist.js -p --display-modules --optimize-minimize", | ||
"dist:sandbox": "webpack --config webpack.config.js -p", | ||
"dist:transpile": "./node_modules/babel-cli/bin/babel.js -d lib src", | ||
"dist": "npm run check && npm-run-all --parallel dist:*", | ||
"docs:lint": "node_modules/documentation/bin/documentation.js lint src/**/*.js", | ||
"docs:watch": "node_modules/documentation/bin/documentation.js --config documentation.yml build src/**/*.js -f html -o gen-docs --watch", | ||
"docs": "npm run docs:lint && node_modules/documentation/bin/documentation.js --config documentation.yml build src/**/*.js -f html -o gen-docs && node_modules/documentation/bin/documentation.js build src/**/*.js -f md > gen-docs/DOCUMENTATION.md", | ||
"functional:local": "export CYPRESS_SANDBOX_URL=http://localhost:3002 && cypress open", | ||
"functional:remote": "export CYPRESS_SANDBOX_URL=https://danielcaldas.github.io/react-d3-graph/sandbox/index.html && cypress open", | ||
"functional": "export CYPRESS_SANDBOX_URL=http://127.0.0.1:8888 && cypress run", | ||
"lint:fix": "node_modules/eslint/bin/eslint.js --config=.eslintrc.js --fix \"src/**/*.js*\" \"sandbox/**/*.js*\"", | ||
"lint:src": "node_modules/eslint/bin/eslint.js --config=.eslintrc.js \"src/**/*.js*\" \"sandbox/**/*.js*\"", | ||
"lint:test": "node_modules/eslint/bin/eslint.js --config=.eslintrc.test.config.js \"test/**/*.spec.js\"", | ||
"lint": "npm run lint:src && npm run lint:test && npm run docs:lint", | ||
"precommit": "lint-staged", | ||
"start": "http-server ./sandbox/ -p 8888 -c-1", | ||
"test:clean": "jest --no-cache --updateSnapshot --verbose --coverage --config jest.config.js", | ||
"test:watch": "jest --verbose --coverage --watchAll --config jest.config.js", | ||
"test": "jest --verbose --coverage --config jest.config.js", | ||
"sandbox": "npm run dist:sandbox && npm run start" | ||
}, | ||
"lint-staged": { | ||
"*.{js,jsx,json,css,md}": [ | ||
"prettier --write", | ||
"git add" | ||
] | ||
}, | ||
"peerDependencies": { | ||
"d3": "^5.5.0", | ||
"react": "^16.4.1" | ||
}, | ||
"devDependencies": { | ||
"@cypress/webpack-preprocessor": "4.1.0", | ||
"babel-cli": "6.26.0", | ||
"babel-core": "6.26.0", | ||
"babel-jest": "23.4.0", | ||
"babel-loader": "7.1.2", | ||
"babel-plugin-add-module-exports": "0.2.1", | ||
"babel-plugin-react-html-attrs": "2.0.0", | ||
"babel-plugin-transform-class-properties": "6.24.1", | ||
"babel-plugin-transform-object-rest-spread": "6.26.0", | ||
"babel-polyfill": "6.26.0", | ||
"babel-preset-es2015": "6.24.1", | ||
"babel-preset-react": "6.24.1", | ||
"babel-preset-stage-2": "6.24.1", | ||
"cross-env": "^5.2.0", | ||
"css-loader": "2.0.2", | ||
"cypress": "3.4.1", | ||
"d3": "^5.5.0", | ||
"documentation": "6.2.0", | ||
"eslint": "4.19.1", | ||
"eslint-config-recommended": "2.0.0", | ||
"eslint-plugin-cypress": "2.6.1", | ||
"eslint-plugin-jest": "21.18.0", | ||
"eslint-plugin-prettier": "^3.0.0", | ||
"eslint-plugin-promise": "3.7.0", | ||
"eslint-plugin-react": "7.10.0", | ||
"eslint-plugin-standard": "3.0.1", | ||
"html-webpack-plugin": "2.30.1", | ||
"http-server": "0.11.1", | ||
"husky": "0.14.3", | ||
"jest": "23.4.1", | ||
"lint-staged": "7.0.0", | ||
"npm-run-all": "4.1.1", | ||
"prettier": "1.15.3", | ||
"query-string": "6.1.0", | ||
"react": "^16.4.1", | ||
"react-addons-test-utils": "15.6.2", | ||
"react-dom": "^16.4.2", | ||
"react-editable-json-tree": "2.2.1", | ||
"react-jsonschema-form": "1.0.4", | ||
"react-test-renderer": "16.4.1", | ||
"style-loader": "0.18.2", | ||
"typescript": "^3.2.2", | ||
"webpack": "4.28.1", | ||
"webpack-bundle-analyzer": "^3.0.3", | ||
"webpack-cli": "2.0.12", | ||
"webpack-dev-server": "^3.1.14", | ||
"webpack-visualizer-plugin": "0.1.11" | ||
}, | ||
"engines": { | ||
"node": ">=8.9.0" | ||
}, | ||
"main": "lib/index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/danielcaldas/react-d3-graph.git" | ||
}, | ||
"keywords": [ | ||
"d3-visualization", | ||
"d3js", | ||
"graphs", | ||
"javascript", | ||
"networks", | ||
"react", | ||
"social-network-analysis", | ||
"social-network-graph", | ||
"visualization" | ||
"name": "react-d3-graph", | ||
"version": "2.3.0", | ||
"description": "React component to build interactive and configurable graphs with d3 effortlessly", | ||
"author": "Daniel Caldas", | ||
"license": "MIT", | ||
"scripts": { | ||
"check": "npm run docs:lint && npm run lint && npm run test && npm run functional", | ||
"check:light": "npm run lint && npm run test", | ||
"dev": "cross-env NODE_ENV=dev webpack-dev-server --mode=development --content-base sandbox --config webpack.config.js --inline --hot --port 3002", | ||
"dist:rd3g": "rm -rf dist/ && webpack --config webpack.config.dist.js -p --display-modules --optimize-minimize", | ||
"dist:sandbox": "webpack --config webpack.config.js -p", | ||
"dist:transpile": "./node_modules/@babel/cli/bin/babel.js -d lib src", | ||
"dist": "npm run check && npm-run-all --parallel dist:*", | ||
"docs:lint": "node_modules/documentation/bin/documentation.js lint src/**/*.js", | ||
"docs:watch": "node_modules/documentation/bin/documentation.js --config documentation.yml build src/**/*.js -f html -o gen-docs --watch", | ||
"docs": "npm run docs:lint && node_modules/documentation/bin/documentation.js --config documentation.yml build src/**/*.js -f html -o gen-docs && node_modules/documentation/bin/documentation.js build src/**/*.js -f md > gen-docs/DOCUMENTATION.md", | ||
"functional:local": "export CYPRESS_SANDBOX_URL=http://localhost:3002 && cypress open", | ||
"functional:remote": "export CYPRESS_SANDBOX_URL=https://danielcaldas.github.io/react-d3-graph/sandbox/index.html && cypress open", | ||
"functional": "export CYPRESS_SANDBOX_URL=http://127.0.0.1:8888 && cypress run", | ||
"lint:fix": "node_modules/eslint/bin/eslint.js --config=.eslintrc.js --fix \"src/**/*.js*\" \"sandbox/**/*.js*\"", | ||
"lint:src": "node_modules/eslint/bin/eslint.js --config=.eslintrc.js \"src/**/*.js*\" \"sandbox/**/*.js*\"", | ||
"lint:test": "node_modules/eslint/bin/eslint.js --config=.eslintrc.test.config.js \"test/**/*.spec.js\"", | ||
"lint": "npm run lint:src && npm run lint:test && npm run docs:lint", | ||
"start": "http-server ./sandbox/ -p 8888 -c-1", | ||
"test:clean": "jest --no-cache --updateSnapshot --verbose --coverage --config jest.config.js", | ||
"test:watch": "jest --verbose --coverage --watchAll --config jest.config.js", | ||
"test": "jest --verbose --coverage --config jest.config.js", | ||
"sandbox": "npm run dist:sandbox && npm run start" | ||
}, | ||
"lint-staged": { | ||
"*.{js,jsx,json,css,md}": [ | ||
"prettier --write", | ||
"git add" | ||
] | ||
}, | ||
"peerDependencies": { | ||
"d3": "^5.5.0", | ||
"react": "^16.4.1" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "7.6.0", | ||
"@babel/core": "7.6.0", | ||
"@babel/plugin-proposal-class-properties": "7.5.5", | ||
"@babel/plugin-proposal-optional-chaining": "7.6.0", | ||
"@babel/preset-env": "7.6.0", | ||
"@babel/preset-react": "7.0.0", | ||
"@cypress/webpack-preprocessor": "4.1.0", | ||
"babel-loader": "8.0.6", | ||
"cross-env": "5.2.1", | ||
"css-loader": "2.0.2", | ||
"cypress": "3.4.1", | ||
"d3": "^5.5.0", | ||
"documentation": "12.1.2", | ||
"eslint": "6.3.0", | ||
"eslint-config-recommended": "4.0.0", | ||
"eslint-plugin-babel": "5.3.0", | ||
"eslint-plugin-cypress": "2.6.1", | ||
"eslint-plugin-jest": "22.17.0", | ||
"eslint-plugin-prettier": "3.1.0", | ||
"eslint-plugin-promise": "4.2.1", | ||
"eslint-plugin-react": "7.14.3", | ||
"eslint-plugin-standard": "4.0.1", | ||
"html-webpack-plugin": "2.30.1", | ||
"http-server": "0.11.1", | ||
"husky": "3.0.5", | ||
"jest": "24.9.0", | ||
"lint-staged": "9.2.5", | ||
"npm-run-all": "4.1.5", | ||
"prettier": "1.18.2", | ||
"query-string": "6.8.3", | ||
"react": "^16.4.1", | ||
"react-addons-test-utils": "15.6.2", | ||
"react-dom": "^16.4.2", | ||
"react-editable-json-tree": "2.2.1", | ||
"react-jsonschema-form": "1.0.4", | ||
"react-test-renderer": "16.9.0", | ||
"style-loader": "0.18.2", | ||
"typescript": "3.6.2", | ||
"webpack": "4.28.1", | ||
"webpack-bundle-analyzer": "^3.0.3", | ||
"webpack-cli": "3.3.8", | ||
"webpack-dev-server": "^3.1.14", | ||
"webpack-visualizer-plugin": "0.1.11" | ||
}, | ||
"engines": { | ||
"node": ">=8.9.0" | ||
}, | ||
"main": "lib/index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/danielcaldas/react-d3-graph.git" | ||
}, | ||
"keywords": [ | ||
"d3-visualization", | ||
"d3js", | ||
"graphs", | ||
"javascript", | ||
"networks", | ||
"react", | ||
"social-network-analysis", | ||
"social-network-graph", | ||
"visualization" | ||
], | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
} | ||
} |
@@ -126,2 +126,6 @@ # react-d3-graph · [![Build Status](https://travis-ci.org/danielcaldas/react-d3-graph.svg?branch=master&style=flat-square)](https://travis-ci.org/danielcaldas/react-d3-graph) | ||
const onNodePositionChange = function(nodeId, x, y) { | ||
window.alert(`Node ${nodeId} is moved to new position. New position is x= ${x} y= ${y}`); | ||
}; | ||
<Graph | ||
@@ -140,2 +144,3 @@ id="graph-id" // id is mandatory, if no id is defined rd3g will throw an error | ||
onMouseOutLink={onMouseOutLink} | ||
onNodePositionChange={onNodePositionChange} | ||
/>; | ||
@@ -148,6 +153,14 @@ ``` | ||
To run react-d3-graph in development mode you just need to run `npm run dev` and the interactive sandbox will reload with the changes to the library code, that way you can test your changes not only through unit test but also through a real life example. It's that simple. | ||
To run react-d3-graph in development mode you just need to run `npm run dev` and the interactive sandbox will reload with the changes to the library code, that way you can test your changes not only through unit test but also through a real life example. It's that simple. The development workflow usually should follow the steps: | ||
- Create a branch prefixed with `fix/` for bug fixes, `feature/` for new features, `chore/` or `refactor/` for refactoring or tolling and CI/CD related tasks. | ||
- Make sure you are up to date running `npm install`. | ||
- Run `npm run dev`. | ||
- Do you changes inside the folder `src` and the interactive sandbox consumes your changes in real time | ||
with webpack-dev-server. | ||
- You can run tests locally with `npm run test` (for unit tests) or `npm run functional:local` for e2e tests. | ||
- After you're done open the Pull Request and describe the changes you've made. | ||
## Alternatives (Not what you where looking for?) | ||
Well if you scrolled this far maybe _react-d3-graph_ does not fulfill all your requirements 😭, but don't worry I got you covered! There are a lot of different and good alternatives out there, [here is a list with a few alternatives](http://anvaka.github.io/graph-drawing-libraries/#!/all#%2Fall). Btw, not in the previous list but also a valid alternative built by uber [uber/react-vis-force](https://github.com/uber/react-vis-force). |
@@ -5,18 +5,6 @@ /** | ||
* Offers a series of methods that allow graph to perform the necessary operations to | ||
* create the collapsible behavior. | ||
* | ||
* Developer notes - collapsing nodes and maintaining state on links matrix. | ||
* | ||
* User interaction flow (for a collapsible graph) | ||
* 1. User clicks node | ||
* 2. All leaf connections of that node are not rendered anymore | ||
* 3. User clicks on same node | ||
* 4. All leaf connections of that node are rendered | ||
* | ||
* Internal react-d3-graph flow | ||
* 1. User clicks node | ||
* 2. Compute leaf connections for clicked node (rootNode, root as in 'root' of the event) | ||
* 3. Update connections matrix (based on 2.) | ||
* 4. Update d3Links array with toggled connections (based on 2.) | ||
* create the collapsible behavior. These functions will most likely operate on | ||
* the links matrix. | ||
*/ | ||
import { getId } from "./graph.helper"; | ||
@@ -57,4 +45,5 @@ /** | ||
const { inDegree, outDegree } = computeNodeDegree(nodeId, linksMatrix); | ||
const fn = directed ? _isLeafDirected : _isLeafNotDirected; | ||
return directed ? _isLeafDirected(inDegree, outDegree) : _isLeafNotDirected(inDegree, outDegree); | ||
return fn(inDegree, outDegree); | ||
} | ||
@@ -83,13 +72,7 @@ | ||
if (nodeId === source) { | ||
return { | ||
..._acc, | ||
outDegree: _acc.outDegree + linksMatrix[nodeId][target], | ||
}; | ||
_acc.outDegree += linksMatrix[nodeId][target]; | ||
} | ||
if (nodeId === target) { | ||
return { | ||
..._acc, | ||
inDegree: _acc.inDegree + linksMatrix[source][nodeId], | ||
}; | ||
_acc.inDegree += linksMatrix[source][nodeId]; | ||
} | ||
@@ -139,3 +122,3 @@ | ||
* If you think that this code is confusing and could potentially collide (🤞) with #_isLeaf | ||
* always remember that *A leaf can, through time, be both a visible or an invisible node!*. | ||
* always remember that *A leaf can, throughout time, both a visible or an invisible node!*. | ||
* | ||
@@ -149,6 +132,9 @@ * @param {string} nodeId - The id of the node to get the cardinality of | ||
function isNodeVisible(nodeId, nodes, linksMatrix) { | ||
if (nodes[nodeId]._orphan) { | ||
return true; | ||
} | ||
const { inDegree, outDegree } = computeNodeDegree(nodeId, linksMatrix); | ||
const orphan = !!nodes[nodeId]._orphan; | ||
return inDegree > 0 || outDegree > 0 || orphan; | ||
return inDegree > 0 || outDegree > 0; | ||
} | ||
@@ -166,8 +152,9 @@ | ||
const { source, target } = d3Link; | ||
const sourceId = source.id || source; | ||
const targetId = target.id || target; | ||
const sourceId = getId(source); | ||
const targetId = getId(target); | ||
// connectionMatrix[sourceId][targetId] can be 0 or non existent | ||
const connection = connectionMatrix && connectionMatrix[sourceId] && connectionMatrix[sourceId][targetId]; | ||
const isHidden = !connection; | ||
return connection ? { ...d3Link, isHidden: false } : { ...d3Link, isHidden: true }; | ||
return { ...d3Link, isHidden }; | ||
}); | ||
@@ -174,0 +161,0 @@ } |
@@ -25,6 +25,5 @@ /** | ||
node.id === (highlightedLink && highlightedLink.target); | ||
const someNodeHighlighted = !!( | ||
highlightedNode || | ||
(highlightedLink && highlightedLink.source && highlightedLink.target) | ||
); | ||
const someLinkHighlighted = highlightedLink && highlightedLink.source && highlightedLink.target; | ||
const someNodeHighlighted = !!(highlightedNode || someLinkHighlighted); | ||
let opacity; | ||
@@ -58,6 +57,6 @@ | ||
const { source, target } = link; | ||
const x1 = (nodes[source] && nodes[source].x) || 0; | ||
const y1 = (nodes[source] && nodes[source].y) || 0; | ||
const x2 = (nodes[target] && nodes[target].x) || 0; | ||
const y2 = (nodes[target] && nodes[target].y) || 0; | ||
const x1 = nodes?.[source]?.x || 0; | ||
const y1 = nodes?.[source]?.y || 0; | ||
const x2 = nodes?.[target]?.x || 0; | ||
const y2 = nodes?.[target]?.y || 0; | ||
@@ -80,7 +79,7 @@ const d = buildLinkPathDefinition({ source: { x: x1, y: y1 }, target: { x: x2, y: y2 } }, config.link.type); | ||
const reasonNode = mainNodeParticipates && nodes[source].highlighted && nodes[target].highlighted; | ||
const reasonLink = | ||
const guiltyNode = mainNodeParticipates && nodes[source].highlighted && nodes[target].highlighted; | ||
const guiltyLink = | ||
source === (highlightedLink && highlightedLink.source) && | ||
target === (highlightedLink && highlightedLink.target); | ||
const highlight = reasonNode || reasonLink; | ||
const highlight = guiltyNode || guiltyLink; | ||
@@ -111,6 +110,6 @@ let opacity = link.opacity || config.link.opacity; | ||
let fontSize = null; | ||
let fontColor = null; | ||
let fontWeight = null; | ||
let label = null; | ||
let fontSize = null, | ||
fontColor = null, | ||
fontWeight = null, | ||
label = null; | ||
@@ -130,19 +129,19 @@ if (config.link.renderLabel) { | ||
return { | ||
markerId, | ||
className: CONST.LINK_CLASS_NAME, | ||
d, | ||
source, | ||
target, | ||
strokeWidth, | ||
stroke, | ||
label, | ||
mouseCursor: config.link.mouseCursor, | ||
fontColor, | ||
fontSize: fontSize * t, | ||
fontWeight, | ||
className: CONST.LINK_CLASS_NAME, | ||
label, | ||
markerId, | ||
mouseCursor: config.link.mouseCursor, | ||
opacity, | ||
source, | ||
stroke, | ||
strokeWidth, | ||
target, | ||
onClickLink: linkCallbacks.onClickLink, | ||
onMouseOutLink: linkCallbacks.onMouseOutLink, | ||
onMouseOverLink: linkCallbacks.onMouseOverLink, | ||
onRightClickLink: linkCallbacks.onRightClickLink, | ||
onMouseOverLink: linkCallbacks.onMouseOverLink, | ||
onMouseOutLink: linkCallbacks.onMouseOutLink, | ||
}; | ||
@@ -204,16 +203,13 @@ } | ||
cursor: config.node.mouseCursor, | ||
cx: (node && node.x) || "0", | ||
cy: (node && node.y) || "0", | ||
cx: node?.x || "0", | ||
cy: node?.y || "0", | ||
dx, | ||
fill, | ||
fontColor, | ||
fontSize: fontSize * t, | ||
dx, | ||
fontWeight: highlight ? config.node.highlightFontWeight : config.node.fontWeight, | ||
id: node.id, | ||
label, | ||
onClickNode: nodeCallbacks.onClickNode, | ||
onRightClickNode: nodeCallbacks.onRightClickNode, | ||
onMouseOverNode: nodeCallbacks.onMouseOverNode, | ||
onMouseOut: nodeCallbacks.onMouseOut, | ||
opacity, | ||
overrideGlobalViewGenerator: !node.viewGenerator && node.svg, | ||
renderLabel: config.node.renderLabel, | ||
@@ -226,3 +222,6 @@ size: nodeSize * t, | ||
viewGenerator: node.viewGenerator || config.node.viewGenerator, | ||
overrideGlobalViewGenerator: !node.viewGenerator && node.svg, | ||
onClickNode: nodeCallbacks.onClickNode, | ||
onMouseOut: nodeCallbacks.onMouseOut, | ||
onMouseOverNode: nodeCallbacks.onMouseOverNode, | ||
onRightClickNode: nodeCallbacks.onRightClickNode, | ||
}; | ||
@@ -229,0 +228,0 @@ } |
@@ -33,3 +33,3 @@ /** | ||
import utils from "../../utils"; | ||
import { isDeepEqual, isEmptyObject, merge, pick, antiPick, throwErr } from "../../utils"; | ||
import { computeNodeDegree } from "./collapse.helper"; | ||
@@ -74,4 +74,4 @@ | ||
return graphLinks.reduce((links, l) => { | ||
const source = l.source.id !== undefined && l.source.id !== null ? l.source.id : l.source; | ||
const target = l.target.id !== undefined && l.target.id !== null ? l.target.id : l.target; | ||
const source = getId(l.source); | ||
const target = getId(l.target); | ||
@@ -116,6 +116,7 @@ if (!links[source]) { | ||
if (!node.hasOwnProperty("x")) { | ||
if (!Object.prototype.hasOwnProperty.call(node, "x")) { | ||
node.x = 0; | ||
} | ||
if (!node.hasOwnProperty("y")) { | ||
if (!Object.prototype.hasOwnProperty.call(node, "y")) { | ||
node.y = 0; | ||
@@ -145,8 +146,10 @@ } | ||
const tmp = d3Links.find(l => l.source.id === link.source && l.target.id === link.target); | ||
const d3Link = tmp && utils.pick(tmp, LINK_PROPS_WHITELIST); | ||
const customProps = utils.antiPick(link, ["source", "target"]); | ||
const d3Link = tmp && pick(tmp, LINK_PROPS_WHITELIST); | ||
const customProps = antiPick(link, ["source", "target"]); | ||
if (d3Link) { | ||
const toggledDirected = | ||
state.config && state.config.hasOwnProperty("directed") && config.directed !== state.config.directed; | ||
state.config && | ||
Object.prototype.hasOwnProperty.call(state.config, "directed") && | ||
config.directed !== state.config.directed; | ||
const refinedD3Link = { | ||
@@ -217,3 +220,3 @@ index, | ||
if (!data.nodes || !data.nodes.length) { | ||
utils.throwErr("Graph", ERRORS.INSUFFICIENT_DATA); | ||
throwErr("Graph", ERRORS.INSUFFICIENT_DATA); | ||
} | ||
@@ -227,11 +230,11 @@ | ||
if (!data.nodes.find(n => n.id === l.source)) { | ||
utils.throwErr("Graph", `${ERRORS.INVALID_LINKS} - "${l.source}" is not a valid source node id`); | ||
throwErr("Graph", `${ERRORS.INVALID_LINKS} - "${l.source}" is not a valid source node id`); | ||
} | ||
if (!data.nodes.find(n => n.id === l.target)) { | ||
utils.throwErr("Graph", `${ERRORS.INVALID_LINKS} - "${l.target}" is not a valid target node id`); | ||
throwErr("Graph", `${ERRORS.INVALID_LINKS} - "${l.target}" is not a valid target node id`); | ||
} | ||
if (l && l.value !== undefined && typeof l.value !== "number") { | ||
utils.throwErr( | ||
throwErr( | ||
"Graph", | ||
@@ -254,3 +257,3 @@ `${ERRORS.INVALID_LINK_VALUE} - found in link with source "${l.source}" and target "${l.target}"` | ||
function _pickId(o) { | ||
return utils.pick(o, ["id"]); | ||
return pick(o, ["id"]); | ||
} | ||
@@ -265,3 +268,3 @@ | ||
function _pickSourceAndTarget(o) { | ||
return utils.pick(o, ["source", "target"]); | ||
return pick(o, ["source", "target"]); | ||
} | ||
@@ -283,18 +286,15 @@ | ||
function checkForGraphElementsChanges(nextProps, currentState) { | ||
const nextNodes = nextProps.data.nodes.map(n => utils.antiPick(n, NODE_PROPERTIES_DISCARD_TO_COMPARE)); | ||
const nextNodes = nextProps.data.nodes.map(n => antiPick(n, NODE_PROPERTIES_DISCARD_TO_COMPARE)); | ||
const nextLinks = nextProps.data.links; | ||
const stateD3Nodes = currentState.d3Nodes.map(n => utils.antiPick(n, NODE_PROPERTIES_DISCARD_TO_COMPARE)); | ||
const stateD3Nodes = currentState.d3Nodes.map(n => antiPick(n, NODE_PROPERTIES_DISCARD_TO_COMPARE)); | ||
const stateD3Links = currentState.d3Links.map(l => ({ | ||
// FIXME: solve this source data inconsistency later | ||
source: l.source.id !== undefined && l.source.id !== null ? l.source.id : l.source, | ||
target: l.target.id !== undefined && l.target.id !== null ? l.target.id : l.target, | ||
source: getId(l.source), | ||
target: getId(l.target), | ||
})); | ||
const graphElementsUpdated = !( | ||
utils.isDeepEqual(nextNodes, stateD3Nodes) && utils.isDeepEqual(nextLinks, stateD3Links) | ||
); | ||
const graphElementsUpdated = !(isDeepEqual(nextNodes, stateD3Nodes) && isDeepEqual(nextLinks, stateD3Links)); | ||
const newGraphElements = | ||
nextNodes.length !== stateD3Nodes.length || | ||
nextLinks.length !== stateD3Links.length || | ||
!utils.isDeepEqual(nextNodes.map(_pickId), stateD3Nodes.map(_pickId)) || | ||
!utils.isDeepEqual(nextLinks.map(_pickSourceAndTarget), stateD3Links.map(_pickSourceAndTarget)); | ||
!isDeepEqual(nextNodes.map(_pickId), stateD3Nodes.map(_pickId)) || | ||
!isDeepEqual(nextLinks.map(_pickSourceAndTarget), stateD3Links.map(_pickSourceAndTarget)); | ||
@@ -315,5 +315,4 @@ return { graphElementsUpdated, newGraphElements }; | ||
const newConfig = nextProps.config || {}; | ||
const configUpdated = | ||
newConfig && !utils.isEmptyObject(newConfig) && !utils.isDeepEqual(newConfig, currentState.config); | ||
const d3ConfigUpdated = newConfig && newConfig.d3 && !utils.isDeepEqual(newConfig.d3, currentState.config.d3); | ||
const configUpdated = newConfig && !isEmptyObject(newConfig) && !isDeepEqual(newConfig, currentState.config); | ||
const d3ConfigUpdated = newConfig && newConfig.d3 && !isDeepEqual(newConfig.d3, currentState.config.d3); | ||
@@ -328,3 +327,3 @@ return { configUpdated, d3ConfigUpdated }; | ||
* @param {Object} config - same as {@link #graphrenderer|config in renderGraph}. | ||
* @returns {string} transform rule to apply. | ||
* @returns {string|undefined} transform rule to apply. | ||
* @memberof Graph/helper | ||
@@ -347,2 +346,21 @@ */ | ||
/** | ||
* This function extracts an id from a link. | ||
* **Why this function?** | ||
* According to [d3-force](https://github.com/d3/d3-force#link_links) | ||
* d3 links might be initialized with "source" and "target" | ||
* properties as numbers or strings, but after initialization they | ||
* are converted to an object. This small utility functions ensures | ||
* that weather in initialization or further into the lifetime of the graph | ||
* we always get the id. | ||
* @param {Object|string|number} sot source or target | ||
* of the link to extract id. | ||
* we want to extract an id. | ||
* @returns {string|number} the id of the link. | ||
* @memberof Graph/helper | ||
*/ | ||
function getId(sot) { | ||
return sot.id !== undefined && sot.id !== null ? sot.id : sot; | ||
} | ||
/** | ||
* Encapsulates common procedures to initialize graph. | ||
@@ -365,3 +383,3 @@ * @param {Object} props - Graph component props, object that holds data, id and config. | ||
nodes: data.nodes.map(n => | ||
state.nodes[n.id] ? { ...n, ...utils.pick(state.nodes[n.id], NODE_PROPS_WHITELIST) } : { ...n } | ||
state.nodes[n.id] ? { ...n, ...pick(state.nodes[n.id], NODE_PROPS_WHITELIST) } : { ...n } | ||
), | ||
@@ -379,9 +397,8 @@ links: data.links.map((l, index) => | ||
let newConfig = { ...utils.merge(DEFAULT_CONFIG, config || {}) }; | ||
let links = _initializeLinks(graph.links, newConfig); // matrix of graph connections | ||
let nodes = _tagOrphanNodes(_initializeNodes(graph.nodes), links); | ||
let newConfig = { ...merge(DEFAULT_CONFIG, config || {}) }, | ||
links = _initializeLinks(graph.links, newConfig), // matrix of graph connections | ||
nodes = _tagOrphanNodes(_initializeNodes(graph.nodes), links); | ||
const { nodes: d3Nodes, links: d3Links } = graph; | ||
const formatedId = id.replace(/ /g, "_"); | ||
const simulation = _createForceSimulation(newConfig.width, newConfig.height, newConfig.d3 && newConfig.d3.gravity); | ||
const { minZoom, maxZoom, focusZoom } = newConfig; | ||
@@ -407,2 +424,3 @@ | ||
transform: 1, | ||
draggedNode: null, | ||
}; | ||
@@ -425,2 +443,3 @@ } | ||
const node = { ...nodes[id], highlighted: value }; | ||
let updatedNodes = { ...nodes, [id]: node }; | ||
@@ -433,3 +452,5 @@ | ||
return { ...acc, [linkId]: updatedNode }; | ||
acc[linkId] = updatedNode; | ||
return acc; | ||
}, updatedNodes); | ||
@@ -448,4 +469,5 @@ } | ||
getCenterAndZoomTransformation, | ||
getId, | ||
initializeGraphState, | ||
updateNodeHighlightedValue, | ||
}; |
@@ -12,6 +12,12 @@ import React from "react"; | ||
import * as collapseHelper from "./collapse.helper"; | ||
import * as graphHelper from "./graph.helper"; | ||
import * as graphRenderer from "./graph.renderer"; | ||
import utils from "../../utils"; | ||
import { getTargetLeafConnections, toggleLinksMatrixConnections, toggleLinksConnections } from "./collapse.helper"; | ||
import { | ||
updateNodeHighlightedValue, | ||
checkForGraphConfigChanges, | ||
checkForGraphElementsChanges, | ||
getCenterAndZoomTransformation, | ||
initializeGraphState, | ||
} from "./graph.helper"; | ||
import { renderGraph } from "./graph.renderer"; | ||
import { merge, throwErr } from "../../utils"; | ||
@@ -94,2 +100,7 @@ /** | ||
* | ||
* const onNodePositionChange = function(nodeId, x, y) { | ||
* window.alert(`Node ${nodeId} moved to new position x= ${x} y= ${y}`); | ||
* }; | ||
* | ||
* | ||
* <Graph | ||
@@ -185,6 +196,12 @@ * id='graph-id' // id is mandatory, if no id is defined rd3g will throw an error | ||
*/ | ||
_onDragEnd = () => | ||
_onDragEnd = () => { | ||
if (this.state.draggedNode) { | ||
this.onNodePositionChange(this.state.draggedNode); | ||
this._tick({ draggedNode: null }); | ||
} | ||
!this.state.config.staticGraph && | ||
this.state.config.automaticRearrangeAfterDropNode && | ||
this.state.simulation.alphaTarget(this.state.config.d3.alphaTarget).restart(); | ||
this.state.config.automaticRearrangeAfterDropNode && | ||
this.state.simulation.alphaTarget(this.state.config.d3.alphaTarget).restart(); | ||
}; | ||
@@ -207,2 +224,5 @@ /** | ||
draggedNode.oldX = draggedNode.x; | ||
draggedNode.oldY = draggedNode.y; | ||
draggedNode.x += d3Event.dx; | ||
@@ -215,3 +235,3 @@ draggedNode.y += d3Event.dy; | ||
this._tick(); | ||
this._tick({ draggedNode }); | ||
} | ||
@@ -238,5 +258,3 @@ }; | ||
_setNodeHighlightedValue = (id, value = false) => | ||
this._tick( | ||
graphHelper.updateNodeHighlightedValue(this.state.nodes, this.state.links, this.state.config, id, value) | ||
); | ||
this._tick(updateNodeHighlightedValue(this.state.nodes, this.state.links, this.state.config, id, value)); | ||
@@ -296,3 +314,3 @@ /** | ||
const tagName = e.target && e.target.tagName; | ||
const name = e.target && e.target.attributes && e.target.attributes.name && e.target.attributes.name.value; | ||
const name = e?.target?.attributes?.name?.value; | ||
const svgContainerName = `svg-container-${this.state.id}`; | ||
@@ -312,14 +330,7 @@ | ||
if (this.state.config.collapsible) { | ||
const leafConnections = collapseHelper.getTargetLeafConnections( | ||
clickedNodeId, | ||
this.state.links, | ||
this.state.config | ||
); | ||
const links = collapseHelper.toggleLinksMatrixConnections( | ||
this.state.links, | ||
leafConnections, | ||
this.state.config | ||
); | ||
const d3Links = collapseHelper.toggleLinksConnections(this.state.d3Links, links); | ||
const firstLeaf = leafConnections && leafConnections.length && leafConnections[0]; | ||
const leafConnections = getTargetLeafConnections(clickedNodeId, this.state.links, this.state.config); | ||
const links = toggleLinksMatrixConnections(this.state.links, leafConnections, this.state.config); | ||
const d3Links = toggleLinksConnections(this.state.d3Links, links); | ||
const firstLeaf = leafConnections?.["0"]; | ||
let isExpanding = false; | ||
@@ -414,2 +425,21 @@ | ||
/** | ||
* Handles node position change. | ||
* @param {Object} node - an object holding information about the dragged node. | ||
* @returns {undefined} | ||
*/ | ||
onNodePositionChange = node => { | ||
if (!this.props.onNodePositionChange) { | ||
return; | ||
} | ||
const { id, oldX, oldY, x, y } = node; | ||
const deltaX = x - oldX; | ||
const deltaY = y - oldY; | ||
if (deltaX !== 0 || deltaY !== 0) { | ||
this.props.onNodePositionChange(id, x, y); | ||
} | ||
}; | ||
/** | ||
* Calls d3 simulation.stop().<br/> | ||
@@ -455,7 +485,8 @@ * {@link https://github.com/d3/d3-force#simulation_stop} | ||
if (!this.props.id) { | ||
utils.throwErr(this.constructor.name, ERRORS.GRAPH_NO_ID_PROP); | ||
throwErr(this.constructor.name, ERRORS.GRAPH_NO_ID_PROP); | ||
} | ||
this.focusAnimationTimeout = null; | ||
this.state = graphHelper.initializeGraphState(this.props, this.state); | ||
this.nodeClickTimer = null; | ||
this.state = initializeGraphState(this.props, this.state); | ||
} | ||
@@ -475,10 +506,7 @@ | ||
UNSAFE_componentWillReceiveProps(nextProps) { | ||
const { graphElementsUpdated, newGraphElements } = graphHelper.checkForGraphElementsChanges( | ||
nextProps, | ||
this.state | ||
); | ||
const state = graphElementsUpdated ? graphHelper.initializeGraphState(nextProps, this.state) : this.state; | ||
const { graphElementsUpdated, newGraphElements } = checkForGraphElementsChanges(nextProps, this.state); | ||
const state = graphElementsUpdated ? initializeGraphState(nextProps, this.state) : this.state; | ||
const newConfig = nextProps.config || {}; | ||
const { configUpdated, d3ConfigUpdated } = graphHelper.checkForGraphConfigChanges(nextProps, this.state); | ||
const config = configUpdated ? utils.merge(DEFAULT_CONFIG, newConfig) : this.state.config; | ||
const { configUpdated, d3ConfigUpdated } = checkForGraphConfigChanges(nextProps, this.state); | ||
const config = configUpdated ? merge(DEFAULT_CONFIG, newConfig) : this.state.config; | ||
@@ -491,3 +519,3 @@ // in order to properly update graph data we need to pause eventual d3 ongoing animations | ||
const d3FocusedNode = this.state.d3Nodes.find(node => `${node.id}` === `${focusedNodeId}`); | ||
const focusTransformation = graphHelper.getCenterAndZoomTransformation(d3FocusedNode, this.state.config); | ||
const focusTransformation = getCenterAndZoomTransformation(d3FocusedNode, this.state.config); | ||
const enableFocusAnimation = this.props.data.focusedNodeId !== nextProps.data.focusedNodeId; | ||
@@ -545,7 +573,16 @@ | ||
this.pauseSimulation(); | ||
this.nodeClickTimer && clearTimeout(this.nodeClickTimer); | ||
if (this.nodeClickTimer) { | ||
clearTimeout(this.nodeClickTimer); | ||
this.nodeClickTimer = null; | ||
} | ||
if (this.focusAnimationTimeout) { | ||
clearTimeout(this.focusAnimationTimeout); | ||
this.focusAnimationTimeout = null; | ||
} | ||
} | ||
render() { | ||
const { nodes, links, defs } = graphRenderer.renderGraph( | ||
const { nodes, links, defs } = renderGraph( | ||
this.state.nodes, | ||
@@ -552,0 +589,0 @@ { |
@@ -15,2 +15,3 @@ /** | ||
import { buildLinkProps, buildNodeProps } from "./graph.builder"; | ||
import { getId } from "../graph/graph.helper"; | ||
import { isNodeVisible } from "./collapse.helper"; | ||
@@ -40,5 +41,4 @@ | ||
const { source, target } = link; | ||
// FIXME: solve this source data inconsistency later | ||
const sourceId = source.id !== undefined && source.id !== null ? source.id : source; | ||
const targetId = target.id !== undefined && target.id !== null ? target.id : target; | ||
const sourceId = getId(source); | ||
const targetId = getId(target); | ||
const key = `${sourceId}${CONST.COORDS_SEPARATOR}${targetId}`; | ||
@@ -45,0 +45,0 @@ const props = buildLinkProps( |
@@ -10,3 +10,2 @@ /** | ||
* This function is a key template builder to access MARKERS structure. | ||
* WARN: function tightly coupled to the MARKERS object in marker.const. | ||
* @param {string} size - string that indicates size of marker. | ||
@@ -13,0 +12,0 @@ * @param {string} highlighted - string that indicates highlight state of marker. |
@@ -96,7 +96,8 @@ import React from "react"; | ||
const size = this.props.size; | ||
let gtx = this.props.cx; | ||
let gty = this.props.cy; | ||
let label; | ||
let node; | ||
let gtx = this.props.cx, | ||
gty = this.props.cy, | ||
label = null, | ||
node = null; | ||
if (this.props.svg || this.props.viewGenerator) { | ||
@@ -103,0 +104,0 @@ const height = size / 10; |
@@ -20,3 +20,9 @@ /** | ||
function _isPropertyNestedObject(o, k) { | ||
return !!o && o.hasOwnProperty(k) && typeof o[k] === "object" && o[k] !== null && !isEmptyObject(o[k]); | ||
return ( | ||
!!o && | ||
Object.prototype.hasOwnProperty.call(o, k) && | ||
typeof o[k] === "object" && | ||
o[k] !== null && | ||
!isEmptyObject(o[k]) | ||
); | ||
} | ||
@@ -56,3 +62,5 @@ | ||
} else { | ||
const r = (isEmptyObject(o1[k]) && isEmptyObject(o2[k])) || (o2.hasOwnProperty(k) && o2[k] === o1[k]); | ||
const r = | ||
(isEmptyObject(o1[k]) && isEmptyObject(o2[k])) || | ||
(Object.prototype.hasOwnProperty.call(o2, k) && o2[k] === o1[k]); | ||
@@ -91,6 +99,4 @@ diffs.push(r); | ||
function deepClone(o, _clone = {}, _depth = 0) { | ||
// TODO: Handle invalid input o is null, undefined, empty object | ||
const oKeys = Object.keys(o); | ||
// TODO: handle arrays | ||
for (let k of oKeys) { | ||
@@ -129,5 +135,8 @@ const nested = _isPropertyNestedObject(o, k); | ||
o[k] = | ||
o1[k].hasOwnProperty("length") && o2[k].hasOwnProperty("length") ? Object.keys(r).map(rk => r[rk]) : r; | ||
Object.prototype.hasOwnProperty.call(o1[k], "length") && | ||
Object.prototype.hasOwnProperty.call(o2[k], "length") | ||
? Object.keys(r).map(rk => r[rk]) | ||
: r; | ||
} else { | ||
o[k] = o2.hasOwnProperty(k) ? o2[k] : o1[k]; | ||
o[k] = Object.prototype.hasOwnProperty.call(o2, k) ? o2[k] : o1[k]; | ||
} | ||
@@ -149,3 +158,3 @@ } | ||
return props.reduce((acc, k) => { | ||
if (o.hasOwnProperty(k)) { | ||
if (Object.prototype.hasOwnProperty.call(o, k)) { | ||
acc[k] = o[k]; | ||
@@ -184,10 +193,2 @@ } | ||
export default { | ||
isDeepEqual, | ||
isEmptyObject, | ||
deepClone, | ||
merge, | ||
pick, | ||
antiPick, | ||
throwErr, | ||
}; | ||
export { isDeepEqual, isEmptyObject, deepClone, merge, pick, antiPick, throwErr }; |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
43
164
413766
54
5226