Skip to content

Commit d9c2cc7

Browse files
committed
Merge branch 'release/v1.2.0'
2 parents da76e20 + 2f594fd commit d9c2cc7

File tree

12 files changed

+261
-90
lines changed

12 files changed

+261
-90
lines changed

.github/ISSUE_TEMPLATE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- [ ] Implementation
2+
- [ ] Unit test
3+
- [ ] Docs

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ React D3 Tree is a [React](http://facebook.github.io/react/) component that lets
1111
- [Installation](#installation)
1212
- [Usage](#usage)
1313
- [Props](#props)
14+
- [Styling](#styling)
1415
- [External data sources](#external-data-sources)
1516

1617

@@ -87,6 +88,39 @@ class MyComponent extends React.Component {
8788
| `zoomable` | `bool` | | | `true` | Toggles ability to zoom in/out on the Tree by scaling it according to `props.scaleExtent`. |
8889
| `scaleExtent` | `object` | | | `{min: 0.1, max: 1}` | Sets the minimum/maximum extent to which the tree can be scaled if `props.zoomable` is true. |
8990
| `transitionDuration` | `number` | `0..n` | | `500` | Sets the animation duration (in ms) of each expansion/collapse of a tree node. <br /><br /> Set this to `0` to deactivate animations completely. |
91+
| `styles` | `object` | see [Styling](#styling) | | `Node`/`Link` CSS files | Overrides and/or enhances the tree's default styling. |
92+
93+
94+
## Styling
95+
The tree's `styles` prop may be used to override any of the tree's default styling.
96+
The following object shape is expected by `styles`:
97+
```js
98+
{
99+
links: <svgStyleObject>,
100+
nodes: {
101+
node: {
102+
circle: <svgStyleObject>,
103+
name: <svgStyleObject>,
104+
attributes: <svgStyleObject>,
105+
},
106+
leafNode: {
107+
circle: <svgStyleObject>,
108+
name: <svgStyleObject>,
109+
attributes: <svgStyleObject>,
110+
},
111+
},
112+
}
113+
```
114+
where `<svgStyleObject>` is any object containing CSS-like properties that are compatible with an `<svg>` element's `style` attribute, for example:
115+
```js
116+
{
117+
stroke: 'blue',
118+
strokeWidth: 3,
119+
}
120+
```
121+
122+
For more information on the SVG `style` attribute, [check this out](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/style).
123+
90124

91125
## External data sources
92126
Statically hosted JSON or CSV files can be used as data sources via the additional `treeUtil` module.

lib/react-d3-tree.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 26 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-d3-tree",
3-
"version": "1.1.1",
3+
"version": "1.2.0",
44
"description": "React component to create interactive D3 tree hierarchies",
55
"main": "lib/react-d3-tree.min.js",
66
"scripts": {
@@ -29,7 +29,7 @@
2929
"coverageThreshold": {
3030
"global": {
3131
"statements": 90,
32-
"branches": 83,
32+
"branches": 82,
3333
"functions": 90,
3434
"lines": 90
3535
}
@@ -42,6 +42,8 @@
4242
"dependencies": {
4343
"clone": "^2.1.1",
4444
"d3": "3.5.17",
45+
"deep-equal": "^1.0.1",
46+
"prop-types": "^15.5.10",
4547
"react-transition-group": "^1.1.3",
4648
"uuid": "^3.0.1"
4749
},
@@ -67,9 +69,9 @@
6769
"jest": "^19.0.2",
6870
"jsdoc-to-markdown": "^3.0.0",
6971
"postcss-loader": "^1.3.3",
70-
"react": "15.4.2",
71-
"react-addons-test-utils": "15.4.2",
72-
"react-dom": "15.4.2",
72+
"react": "^15.6.0",
73+
"react-dom": "^15.6.0",
74+
"react-test-renderer": "^15.5.4",
7375
"regenerator-runtime": "^0.10.5",
7476
"rimraf": "^2.6.1",
7577
"style-loader": "^0.17.0",

src/Link/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React, { PropTypes } from 'react';
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
23
import { svg, select } from 'd3';
34

45
import './style.css';
@@ -53,10 +54,11 @@ export default class Link extends React.PureComponent {
5354
}
5455

5556
render() {
57+
const { styles } = this.props;
5658
return (
5759
<path
5860
ref={(l) => { this.link = l; }}
59-
style={this.state.initialStyle}
61+
style={{ ...this.state.initialStyle, ...styles }}
6062
className="linkBase"
6163
d={this.drawPath()}
6264
/>
@@ -75,4 +77,5 @@ Link.propTypes = {
7577
'elbow',
7678
]).isRequired,
7779
transitionDuration: PropTypes.number.isRequired,
80+
styles: PropTypes.object.isRequired,
7881
};

src/Link/tests/index.test.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { shallow, mount } from 'enzyme';
33

44
import Link from '../index';
55

6+
// TODO Find a way to meaningfully test `componentWillLeave`
67
describe('<Link />', () => {
78
const linkData = {
89
source: {
@@ -20,6 +21,7 @@ describe('<Link />', () => {
2021
pathFunc: 'diagonal',
2122
orientation: 'horizontal',
2223
transitionDuration: 500,
24+
styles: {},
2325
};
2426

2527

@@ -40,6 +42,20 @@ describe('<Link />', () => {
4042
});
4143

4244

45+
it('applies `props.styles` when defined', () => {
46+
const initialStyle = { opacity: 0 }; // state.initialStyle
47+
const fixture = { ...initialStyle, stroke: '#777', strokeWidth: 2 };
48+
const renderedComponent = shallow(
49+
<Link
50+
{...mockProps}
51+
styles={fixture}
52+
/>
53+
);
54+
55+
expect(renderedComponent.prop('style')).toEqual(fixture);
56+
});
57+
58+
4359
it('calls the appropriate path func based on `props.pathFunc`', () => {
4460
const diagonalComponent = shallow(
4561
<Link {...mockProps} />
@@ -74,6 +90,4 @@ describe('<Link />', () => {
7490

7591
expect(renderedComponent.instance().applyOpacity).toHaveBeenCalledWith(fixture);
7692
});
77-
78-
// TODO Find a way to meaningfully test `componentWillLeave`
7993
});

src/Node/index.js

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React, { PropTypes } from 'react';
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
23
import uuid from 'uuid';
34
import { select } from 'd3';
45

@@ -65,8 +66,8 @@ export default class Node extends React.Component {
6566
}
6667

6768
render() {
68-
const { nodeData } = this.props;
69-
69+
const { nodeData, styles } = this.props;
70+
const nodeStyle = nodeData._children ? { ...styles.node } : { ...styles.leafNode };
7071
return (
7172
<g
7273
id={nodeData.id}
@@ -77,54 +78,47 @@ export default class Node extends React.Component {
7778
onClick={this.handleClick}
7879
>
7980
<text
80-
className="primaryLabelBase"
81+
className="nodeNameBase"
8182
textAnchor={this.props.textAnchor}
82-
style={this.props.primaryLabelStyle}
83+
style={nodeStyle.name}
8384
x="10"
8485
y="-10"
8586
dy=".35em"
8687
>
87-
{this.props.primaryLabel}
88+
{this.props.name}
8889
</text>
8990

9091
<circle
9192
r={this.props.circleRadius}
92-
style={nodeData._children ? this.props.circleStyle : this.props.leafCircleStyle}
93+
style={nodeStyle.circle}
9394
/>
9495

9596
<text
96-
className="secondaryLabelsBase"
97+
className="nodeAttributesBase"
9798
y="0"
9899
textAnchor={this.props.textAnchor}
99-
style={this.props.secondaryLabelsStyle}
100+
style={nodeStyle.attributes}
100101
>
101-
{this.props.secondaryLabels && Object.keys(this.props.secondaryLabels).map((labelKey) =>
102-
<tspan x="10" dy="1.2em" key={uuid.v4()}>
103-
{labelKey}: {this.props.secondaryLabels[labelKey]}
104-
</tspan>
105-
)}
102+
{
103+
this.props.attributes &&
104+
Object.keys(this.props.attributes).map((labelKey) =>
105+
<tspan x="10" dy="1.2em" key={uuid.v4()}>
106+
{labelKey}: {this.props.attributes[labelKey]}
107+
</tspan>
108+
)
109+
}
106110
</text>
107111
</g>
108112
);
109113
}
110114
}
111115

112116
Node.defaultProps = {
113-
depthFactor: undefined,
114117
circleRadius: 10,
115-
circleStyle: {
116-
stroke: '#000',
117-
strokeWidth: 2,
118-
fill: 'grey',
119-
},
120-
leafCircleStyle: {
121-
stroke: '#000',
122-
strokeWidth: 2,
123-
fill: 'transparent',
124-
},
118+
textAnchor: 'start',
119+
attributes: undefined,
125120
};
126121

127-
/* eslint-disable */
128122
Node.propTypes = {
129123
nodeData: PropTypes.object.isRequired,
130124
orientation: PropTypes.oneOf([
@@ -133,14 +127,9 @@ Node.propTypes = {
133127
]).isRequired,
134128
transitionDuration: PropTypes.number.isRequired,
135129
onClick: PropTypes.func.isRequired,
136-
depthFactor: PropTypes.number,
137-
primaryLabel: PropTypes.string,
138-
primaryLabelStyle: PropTypes.object,
139-
secondaryLabels: PropTypes.object,
140-
secondaryLabelsStyle: PropTypes.object,
130+
name: PropTypes.string.isRequired,
131+
attributes: PropTypes.object,
141132
textAnchor: PropTypes.string,
142133
circleRadius: PropTypes.number,
143-
circleStyle: PropTypes.object,
144-
leafCircleStyle: PropTypes.object,
134+
styles: PropTypes.object.isRequired,
145135
};
146-
/* eslint-enable */

src/Node/style.css

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
.nodeBase {
22
cursor: pointer;
3+
fill: #777;
4+
stroke: #000;
5+
stroke-width: 2;
36
}
47

58
.leafNodeBase {
69
cursor: pointer;
10+
fill: transparent;
11+
stroke: #000;
12+
stroke-width: 2;
713
}
814

9-
.primaryLabelBase {
10-
fill: #000;
15+
.nodeNameBase {
16+
stroke: #000;
17+
stroke-width: 1;
1118
}
1219

13-
.secondaryLabelsBase {
14-
fill: #777;
20+
.nodeAttributesBase {
21+
stroke: #777;
22+
stroke-width: 1;
1523
font-size: smaller;
16-
}
24+
}

0 commit comments

Comments
 (0)