react-d3-dag
Version:
React component to create interactive D3 directed acyclic graphs (DAGs)
117 lines (116 loc) • 4.91 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importDefault(require("react"));
const d3_selection_1 = require("d3-selection");
const DefaultNodeElement_js_1 = __importDefault(require("./DefaultNodeElement.js"));
class Node extends react_1.default.Component {
constructor() {
super(...arguments);
this.nodeRef = null;
this.state = {
transform: this.setTransform(this.props.position, this.props.orientation, true),
initialStyle: {
opacity: 0,
},
wasClicked: false,
};
this.shouldNodeTransform = (ownProps, nextProps, ownState, nextState) => nextProps.subscriptions !== ownProps.subscriptions ||
nextProps.position.x !== ownProps.position.x ||
nextProps.position.y !== ownProps.position.y ||
nextProps.orientation !== ownProps.orientation ||
nextState.wasClicked !== ownState.wasClicked;
// TODO: needs tests
this.renderNodeElement = () => {
const { data, dagNode, renderCustomNodeElement } = this.props;
const renderNode = typeof renderCustomNodeElement === 'function' ? renderCustomNodeElement : DefaultNodeElement_js_1.default;
const nodeProps = {
dagNode,
nodeDatum: data,
toggleNode: this.handleNodeToggle,
onNodeClick: this.handleOnClick,
onNodeMouseOver: this.handleOnMouseOver,
onNodeMouseOut: this.handleOnMouseOut,
addChildren: this.handleAddChildren,
};
return renderNode(nodeProps);
};
this.handleNodeToggle = () => {
this.setState({ wasClicked: true });
this.props.onNodeToggle(this.props.data.__rd3dag.id);
};
this.handleOnClick = evt => {
this.setState({ wasClicked: true });
this.props.onNodeClick(this.props.dagNode, evt);
};
this.handleOnMouseOver = evt => {
this.props.onNodeMouseOver(this.props.dagNode, evt);
};
this.handleOnMouseOut = evt => {
this.props.onNodeMouseOut(this.props.dagNode, evt);
};
this.handleAddChildren = childrenData => {
this.props.handleAddChildrenToNode(this.props.data.__rd3dag.id, childrenData);
};
}
componentDidMount() {
this.commitTransform();
}
componentDidUpdate() {
if (this.state.wasClicked) {
this.props.centerNode(this.props.dagNode);
this.setState({ wasClicked: false });
}
this.commitTransform();
}
shouldComponentUpdate(nextProps, nextState) {
return this.shouldNodeTransform(this.props, nextProps, this.state, nextState);
}
setTransform(position, orientation, shouldTranslateToOrigin = false) {
if (shouldTranslateToOrigin) {
return `translate(0,0)`;
}
return orientation === 'horizontal'
? `translate(${position.y},${position.x})`
: `translate(${position.x},${position.y})`;
}
applyTransform(transform, transitionDuration, opacity = 1, done = () => { }) {
if (this.props.enableLegacyTransitions) {
(0, d3_selection_1.select)(this.nodeRef)
// @ts-ignore
.transition()
.duration(transitionDuration)
.attr('transform', transform)
.style('opacity', opacity)
.on('end', done);
}
else {
(0, d3_selection_1.select)(this.nodeRef).attr('transform', transform).style('opacity', opacity);
done();
}
}
commitTransform() {
const { orientation, transitionDuration, position } = this.props;
const transform = this.setTransform(position, orientation);
this.applyTransform(transform, transitionDuration);
}
componentWillLeave(done) {
const { orientation, transitionDuration, position } = this.props;
const transform = this.setTransform(position, orientation, true);
this.applyTransform(transform, transitionDuration, 0, done);
}
render() {
const { data, nodeClassName } = this.props;
return (react_1.default.createElement("g", { id: data.__rd3dag.id, ref: n => {
this.nodeRef = n;
}, style: this.state.initialStyle, className: [
data.children && data.children.length > 0 ? 'rd3dag-node' : 'rd3dag-leaf-node',
nodeClassName,
]
.join(' ')
.trim(), transform: this.state.transform }, this.renderNodeElement()));
}
}
exports.default = Node;