Skip to content

Commit f28a1aa

Browse files
committed
Allows root node object without wrapper array for props.data (#145)
1 parent e78b723 commit f28a1aa

File tree

2 files changed

+42
-43
lines changed

2 files changed

+42
-43
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class MyComponent extends React.Component {
8989
## Props
9090
| Property | Type | Options | Required? | Default | Description |
9191
|:------------------------------|:-----------------------|:---------------------------------------------------------------------------------------|:----------|:--------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
92-
| `data` | `array` | | required | `undefined` | Single-element array containing hierarchical object (see `myTreeData` above). <br /> Contains (at least) `name` and `parent` keys. |
92+
| `data` | `array|object` | | required | `undefined` | Single-element array containing the root node object (see `myTreeData` above). <br /> Contains (at least) a `name` property. <br/> Passing the root node object without an array wrapping it is also possible. |
9393
| `nodeSvgShape` | `object` | see [Node shapes](#node-shapes) | | `{shape: 'circle', shapeProps: {r: 10}}` | Sets a specific SVG shape element + shapeProps to be used for each node. |
9494
| `nodeLabelComponent` | `object` | see [Using foreignObjects](#using-foreignobjects) | | `null` | Allows using a React component as a node label; requires `allowForeignObjects` to be set. |
9595
| `onClick` | `func` | | | `undefined` | Callback function to be called when a node is clicked. <br /><br />Has the function signature `(nodeData, evt)`. The clicked node's data object is passed as first parameter, event object as second. |

src/Tree/index.js

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import PropTypes from 'prop-types';
2+
import T from 'prop-types';
33
import { layout, select, behavior, event } from 'd3';
44
import clone from 'clone';
55
import deepEqual from 'deep-equal';
@@ -145,7 +145,9 @@ export default class Tree extends React.Component {
145145
* @return {array} `data` array with internal properties added
146146
*/
147147
assignInternalProperties(data) {
148-
return data.map(node => {
148+
// Wrap the root node into an array for recursive transformations if it wasn't in one already.
149+
const d = Array.isArray(data) ? data : [data];
150+
return d.map(node => {
149151
node.id = uuid.v4();
150152
// If the node's `_collapsed` state wasn't defined by the data set -> default to `false`.
151153
if (node._collapsed === undefined) {
@@ -517,50 +519,47 @@ Tree.defaultProps = {
517519
};
518520

519521
Tree.propTypes = {
520-
data: PropTypes.array.isRequired,
521-
nodeSvgShape: PropTypes.shape({
522-
shape: PropTypes.string,
523-
shapeProps: PropTypes.object,
522+
data: T.oneOfType([T.array, T.object]).isRequired,
523+
nodeSvgShape: T.shape({
524+
shape: T.string,
525+
shapeProps: T.object,
524526
}),
525-
nodeLabelComponent: PropTypes.object,
526-
onClick: PropTypes.func,
527-
onMouseOver: PropTypes.func,
528-
onMouseOut: PropTypes.func,
529-
onUpdate: PropTypes.func,
530-
orientation: PropTypes.oneOf(['horizontal', 'vertical']),
531-
translate: PropTypes.shape({
532-
x: PropTypes.number,
533-
y: PropTypes.number,
527+
nodeLabelComponent: T.object,
528+
onClick: T.func,
529+
onMouseOver: T.func,
530+
onMouseOut: T.func,
531+
onUpdate: T.func,
532+
orientation: T.oneOf(['horizontal', 'vertical']),
533+
translate: T.shape({
534+
x: T.number,
535+
y: T.number,
534536
}),
535-
pathFunc: PropTypes.oneOfType([
536-
PropTypes.oneOf(['diagonal', 'elbow', 'straight']),
537-
PropTypes.func,
538-
]),
539-
transitionDuration: PropTypes.number,
540-
depthFactor: PropTypes.number,
541-
collapsible: PropTypes.bool,
542-
useCollapseData: PropTypes.bool,
543-
initialDepth: PropTypes.number,
544-
zoomable: PropTypes.bool,
545-
zoom: PropTypes.number,
546-
scaleExtent: PropTypes.shape({
547-
min: PropTypes.number,
548-
max: PropTypes.number,
537+
pathFunc: T.oneOfType([T.oneOf(['diagonal', 'elbow', 'straight']), T.func]),
538+
transitionDuration: T.number,
539+
depthFactor: T.number,
540+
collapsible: T.bool,
541+
useCollapseData: T.bool,
542+
initialDepth: T.number,
543+
zoomable: T.bool,
544+
zoom: T.number,
545+
scaleExtent: T.shape({
546+
min: T.number,
547+
max: T.number,
549548
}),
550-
nodeSize: PropTypes.shape({
551-
x: PropTypes.number,
552-
y: PropTypes.number,
549+
nodeSize: T.shape({
550+
x: T.number,
551+
y: T.number,
553552
}),
554-
separation: PropTypes.shape({
555-
siblings: PropTypes.number,
556-
nonSiblings: PropTypes.number,
553+
separation: T.shape({
554+
siblings: T.number,
555+
nonSiblings: T.number,
557556
}),
558-
textLayout: PropTypes.object,
559-
allowForeignObjects: PropTypes.bool,
560-
shouldCollapseNeighborNodes: PropTypes.bool,
561-
circleRadius: PropTypes.number,
562-
styles: PropTypes.shape({
563-
nodes: PropTypes.object,
564-
links: PropTypes.object,
557+
textLayout: T.object,
558+
allowForeignObjects: T.bool,
559+
shouldCollapseNeighborNodes: T.bool,
560+
circleRadius: T.number,
561+
styles: T.shape({
562+
nodes: T.object,
563+
links: T.object,
565564
}),
566565
};

0 commit comments

Comments
 (0)