Skip to content

Commit 74960f5

Browse files
authored
Update README.md
1 parent e3e53ad commit 74960f5

File tree

1 file changed

+125
-131
lines changed

1 file changed

+125
-131
lines changed

README.md

Lines changed: 125 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -25,153 +25,147 @@ Demo: http://cheton.github.io/react-infinite-tree
2525
npm install --save react-infinite-tree
2626
```
2727

28-
## Example
28+
## Usage
29+
30+
### Tree Structure
31+
32+
A tree structure can either be a node object or an array of node objects, and each node should have a unique `id`. Note that `id`, `state`, `children`, and `parent` are reserved keys for defining a node. See below for a basic tree structure:
33+
34+
```js
35+
{
36+
id: 'fruit',
37+
name: 'Fruit',
38+
children: [{
39+
id: 'apple',
40+
name: 'Apple'
41+
}, {
42+
id: 'banana',
43+
name: 'Banana',
44+
children: [{
45+
id: 'cherry',
46+
name: 'Cherry',
47+
loadOnDemand: true
48+
}]
49+
}]
50+
}
51+
```
2952

30-
### Components
53+
### Rendering Tree Nodes
54+
55+
You can use `rowRenderer` or pass a child function for rendering tree nodes. The child function will be supplied with the following properties:
3156

32-
https://github.com/cheton/react-infinite-tree/tree/master/examples/components
57+
* `tree` - https://github.com/cheton/infinite-tree/wiki/Functions:-Tree
58+
* `node` - https://github.com/cheton/infinite-tree/wiki/Functions:-Node
3359

34-
### Tree
3560

3661
```jsx
37-
import PropTypes from 'prop-types';
38-
import React, { PureComponent } from 'react';
62+
import React from 'react';
3963
import InfiniteTree from 'react-infinite-tree';
40-
import TreeNode from './components/TreeNode';
41-
import Toggler from './components/Toggler';
42-
import Icon from './components/Icon';
43-
import Clickable from './components/Clickable';
44-
import Text from './components/Text';
45-
import Label from './components/Label';
46-
import Loading from './components/Loading';
47-
import { generate } from './tree-generator';
48-
49-
const renderTreeNode = ({ node, tree, toggleState }) => (
50-
<TreeNode
51-
selected={node.state.selected}
52-
depth={node.state.depth}
53-
onClick={event => {
54-
tree.selectNode(node);
55-
}}
64+
65+
export default (props) => (
66+
<InfiniteTree
67+
width="100%"
68+
height={400}
69+
rowHeight={30}
70+
data={props.data}
5671
>
57-
<Toggler
58-
state={toggleState}
59-
onClick={() => {
60-
if (toggleState === 'closed') {
61-
tree.openNode(node);
62-
} else if (toggleState === 'opened') {
63-
tree.closeNode(node);
64-
}
65-
}}
66-
/>
67-
<Clickable>
68-
<Icon state={toggleState} />
69-
<Text>{node.name}</Text>
70-
</Clickable>
71-
{(node.loadOnDemand && node.children.length === 0 && !node.state.loading) &&
72-
<i className="fa fa-fw fa-ellipsis-v" />
72+
{({ tree, node }) => {
73+
// Determine the toggle state
74+
let toggleState = '';
75+
const hasChildren = node.hasChildren();
76+
if ((!hasChildren && node.loadOnDemand) || (hasChildren && !node.state.open)) {
77+
toggleState = 'closed';
7378
}
74-
{node.state.loading && <Loading />}
75-
<Label style={{ position: 'absolute', right: 5, top: 6 }}>
76-
{node.children.length}
77-
</Label>
78-
</TreeNode>
79-
);
80-
81-
class Tree extends PureComponent {
82-
tree = null;
83-
data = generate(1000);
84-
85-
componentDidMount() {
86-
// Select the first node
87-
this.tree.selectNode(this.tree.getChildNodes()[0]);
88-
}
89-
render() {
79+
if (hasChildren && node.state.open) {
80+
toggleState = 'opened';
81+
}
82+
9083
return (
91-
<InfiniteTree
92-
ref={node => {
93-
this.tree = node ? node.tree : null;
94-
}}
95-
style={{
96-
border: '1px solid #ccc'
97-
}}
98-
autoOpen
99-
selectable
100-
tabIndex={0}
101-
data={this.data}
102-
width="100%"
103-
height={400}
104-
rowHeight={30}
105-
rowRenderer={({ node, tree }) => {
106-
const hasChildren = node.hasChildren();
107-
let toggleState = '';
108-
if ((!hasChildren && node.loadOnDemand) || (hasChildren && !node.state.open)) {
109-
toggleState = 'closed';
110-
}
111-
if (hasChildren && node.state.open) {
112-
toggleState = 'opened';
113-
}
114-
return renderTreeNode({ node, tree, toggleState });
84+
<TreeNode
85+
selected={node.state.selected}
86+
depth={node.state.depth}
87+
onClick={event => {
88+
tree.selectNode(node);
11589
}}
116-
loadNodes={(parentNode, done) => {
117-
const suffix = parentNode.id.replace(/(\w)+/, '');
118-
const nodes = [
119-
{
120-
id: 'node1' + suffix,
121-
name: 'Node 1'
122-
},
123-
{
124-
id: 'node2' + suffix,
125-
name: 'Node 2'
90+
>
91+
<Toggler
92+
state={toggleState}
93+
onClick={() => {
94+
if (toggleState === 'closed') {
95+
tree.openNode(node);
96+
} else if (toggleState === 'opened') {
97+
tree.closeNode(node);
12698
}
127-
];
128-
setTimeout(() => {
129-
done(null, nodes);
130-
}, 1000);
131-
}}
132-
shouldSelectNode={(node) => { // Defaults to null
133-
if (!node || (node === this.tree.getSelectedNode())) {
134-
return false; // Prevent from deselecting the current node
135-
}
136-
return true;
137-
}}
138-
onKeyUp={(event) => {
139-
console.log('onKeyUp', event.target);
140-
}}
141-
onKeyDown={(event) => {
142-
console.log('onKeyDown', event.target);
143-
event.preventDefault();
144-
const node = this.tree.getSelectedNode();
145-
const nodeIndex = this.tree.getSelectedIndex();
146-
if (event.keyCode === 37) { // Left
147-
this.tree.closeNode(node);
148-
} else if (event.keyCode === 38) { // Up
149-
const prevNode = this.tree.nodes[nodeIndex - 1] || node;
150-
this.tree.selectNode(prevNode);
151-
} else if (event.keyCode === 39) { // Right
152-
this.tree.openNode(node);
153-
} else if (event.keyCode === 40) { // Down
154-
const nextNode = this.tree.nodes[nodeIndex + 1] || node;
155-
this.tree.selectNode(nextNode);
156-
}
157-
}}
158-
onScroll={(scrollOffset, event) => {}}
159-
onContentWillUpdate={() => {}}
160-
onContentDidUpdate={() => {}}
161-
onOpenNode={(node) => {}}
162-
onCloseNode={(node) => {}}
163-
onSelectNode={(node) => {}}
164-
onWillOpenNode={(node) => {}}
165-
onWillCloseNode={(node) => {}}
166-
onWillSelectNode={(node) => {}}
167-
/>
99+
}}
100+
/>
101+
<span>{node.name}</span>
102+
</TreeNode>
168103
);
104+
}}
105+
</InfiniteTree>
106+
);
107+
```
108+
109+
### Components
110+
111+
#### TreeNode Component
112+
113+
```jsx
114+
import React from 'react';
115+
import styled from 'styled-components';
116+
117+
const defaultRowHeight = 30;
118+
119+
const TreeNode = styled.div`
120+
cursor: default;
121+
position: relative;
122+
line-height: ${({ rowHeight = defaultRowHeight }) => rowHeight - 2}px;
123+
background: ${props => props.selected ? '#deecfd' : 'transparent'};
124+
border: ${props => props.selected ? '1px solid #06c' : '1px solid transparent'};
125+
padding-left: ${props => props.depth * 18}px;
126+
.dropdown {
127+
visibility: hidden;
169128
}
170-
}
129+
&:hover {
130+
background: #f2fdff;
131+
.dropdown {
132+
visibility: inherit;
133+
}
134+
}
135+
`;
136+
137+
export default TreeNode;
138+
```
139+
140+
#### Toggler Component
171141

172-
export default Tree;
142+
```jsx
143+
import React from 'react';
144+
import styled from 'styled-components';
145+
146+
const Toggler = styled(({ state, ...props }) => (
147+
<a {...props}>
148+
{(state === 'closed') &&
149+
<i className="fa fa-fw fa-chevron-right" />
150+
}
151+
{(state === 'opened') &&
152+
<i className="fa fa-fw fa-chevron-down" />
153+
}
154+
</a>
155+
))`
156+
color: #333;
157+
display: inline-block;
158+
text-align: center;
159+
margin-right: 2px;
160+
`;
161+
162+
export default Toggler;
173163
```
174164

165+
## Example
166+
167+
See https://github.com/cheton/react-infinite-tree/blob/master/examples/Tree.jsx for a complete example.
168+
175169
# API
176170

177171
### Properties

0 commit comments

Comments
 (0)