Skip to content

Commit 2f4c914

Browse files
committed
feat: improve approach of sending additional data to node
1 parent 2ff58b4 commit 2f4c914

File tree

9 files changed

+393
-402
lines changed

9 files changed

+393
-402
lines changed

__stories__/FixedSizeTree.story.tsx

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import {number, withKnobs} from '@storybook/addon-knobs';
22
import {storiesOf} from '@storybook/react';
33
import * as React from 'react';
44
import AutoSizer from 'react-virtualized-auto-sizer';
5-
import Tree from '../src/FixedSizeTree';
6-
import {CommonNodeComponentProps, CommonNodeMetadata} from '../src/utils';
5+
import Tree, {
6+
FixedSizeNodeComponentProps,
7+
FixedSizeNodeData,
8+
} from '../src/FixedSizeTree';
79

810
document.body.style.margin = '0';
911
document.body.style.display = 'flex';
@@ -12,16 +14,22 @@ const root = document.getElementById('root')!;
1214
root.style.margin = '10px 0 0 10px';
1315
root.style.flex = '1';
1416

15-
interface DataNode {
17+
type DataNode = {
1618
children: DataNode[];
1719
id: number;
1820
name: string;
19-
}
21+
};
2022

21-
interface StackElement {
23+
type StackElement = {
2224
nestingLevel: number;
2325
node: DataNode;
24-
}
26+
};
27+
28+
type ExtendedData = {
29+
readonly isLeaf: boolean;
30+
readonly name: string;
31+
readonly nestingLevel: number;
32+
};
2533

2634
let nodeId = 0;
2735

@@ -52,7 +60,7 @@ const defaultButtonStyle = {fontFamily: 'Courier New'};
5260

5361
function* treeWalker(
5462
refresh: boolean,
55-
): IterableIterator<CommonNodeMetadata | string | symbol> {
63+
): IterableIterator<FixedSizeNodeData<ExtendedData> | string | symbol> {
5664
const stack: StackElement[] = [];
5765

5866
stack.push({
@@ -66,10 +74,10 @@ function* treeWalker(
6674

6775
const isOpened = yield refresh
6876
? {
69-
childrenCount: node.children.length,
70-
data: node.name,
7177
id,
78+
isLeaf: node.children.length === 0,
7279
isOpenByDefault: true,
80+
name: node.name,
7381
nestingLevel,
7482
}
7583
: id;
@@ -86,34 +94,27 @@ function* treeWalker(
8694
}
8795
}
8896

89-
const Node: React.FunctionComponent<CommonNodeComponentProps> = ({
90-
metadata: {childrenCount, data, nestingLevel},
91-
isOpen,
92-
style,
93-
toggle,
94-
}) => {
95-
const isLeaf = childrenCount === 0;
96-
97-
return (
98-
<div
99-
style={{
100-
...style,
101-
alignItems: 'center',
102-
display: 'flex',
103-
marginLeft: nestingLevel * 30 + (isLeaf ? 48 : 0),
104-
}}
105-
>
106-
{!isLeaf && (
107-
<div>
108-
<button type="button" onClick={toggle} style={defaultButtonStyle}>
109-
{isOpen ? '-' : '+'}
110-
</button>
111-
</div>
112-
)}
113-
<div style={defaultTextStyle}>{data}</div>
114-
</div>
115-
);
116-
};
97+
const Node: React.FunctionComponent<
98+
FixedSizeNodeComponentProps<ExtendedData>
99+
> = ({data: {isLeaf, name, nestingLevel}, isOpen, style, toggle}) => (
100+
<div
101+
style={{
102+
...style,
103+
alignItems: 'center',
104+
display: 'flex',
105+
marginLeft: nestingLevel * 30 + (isLeaf ? 48 : 0),
106+
}}
107+
>
108+
{!isLeaf && (
109+
<div>
110+
<button type="button" onClick={toggle} style={defaultButtonStyle}>
111+
{isOpen ? '-' : '+'}
112+
</button>
113+
</div>
114+
)}
115+
<div style={defaultTextStyle}>{name}</div>
116+
</div>
117+
);
117118

118119
interface TreePresenterProps {
119120
readonly itemSize: number;
@@ -124,7 +125,7 @@ const TreePresenter: React.FunctionComponent<TreePresenterProps> = ({
124125
}) => (
125126
<AutoSizer disableWidth>
126127
{({height}) => (
127-
<Tree
128+
<Tree<ExtendedData>
128129
treeWalker={treeWalker}
129130
itemSize={itemSize}
130131
height={height}

__stories__/VariableSizeTree.story.tsx

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as React from 'react';
44
import AutoSizer from 'react-virtualized-auto-sizer';
55
import Tree, {
66
VariableSizeNodeComponentProps,
7-
VariableSizeNodeMetadata,
7+
VariableSizeNodeData,
88
} from '../src/VariableSizeTree';
99

1010
document.body.style.margin = '0';
@@ -14,16 +14,22 @@ const root = document.getElementById('root')!;
1414
root.style.margin = '10px 0 0 10px';
1515
root.style.flex = '1';
1616

17-
interface DataNode {
17+
type DataNode = {
1818
children: DataNode[];
1919
id: number;
2020
name: string;
21-
}
21+
};
2222

23-
interface StackElement {
23+
type StackElement = {
2424
nestingLevel: number;
2525
node: DataNode;
26-
}
26+
};
27+
28+
type ExtendedData = {
29+
readonly isLeaf: boolean;
30+
readonly name: string;
31+
readonly nestingLevel: number;
32+
};
2733

2834
let nodeId = 0;
2935

@@ -52,16 +58,17 @@ const rootNode = createNode();
5258
const defaultGapStyle = {marginLeft: 10};
5359
const defaultButtonStyle = {fontFamily: 'Courier New'};
5460

55-
const Node: React.FunctionComponent<VariableSizeNodeComponentProps> = ({
56-
data: itemSize,
61+
const Node: React.FunctionComponent<
62+
VariableSizeNodeComponentProps<ExtendedData>
63+
> = ({
5764
height,
58-
metadata: {childrenCount, data, nestingLevel},
65+
data: {isLeaf, name, nestingLevel},
5966
isOpen,
6067
resize,
6168
style,
6269
toggle,
70+
treeData: itemSize,
6371
}) => {
64-
const isLeaf = childrenCount === 0;
6572
const canOpen = height <= itemSize;
6673
const halfSize = itemSize / 2;
6774

@@ -87,7 +94,7 @@ const Node: React.FunctionComponent<VariableSizeNodeComponentProps> = ({
8794
</button>
8895
</div>
8996
)}
90-
<div style={defaultGapStyle}>{data}</div>
97+
<div style={defaultGapStyle}>{name}</div>
9198
<div>
9299
<button type="button" onClick={toggleNodeSize} style={defaultGapStyle}>
93100
{canOpen ? 'Open' : 'Close'}
@@ -104,12 +111,12 @@ interface TreePresenterProps {
104111
const TreePresenter: React.FunctionComponent<TreePresenterProps> = ({
105112
itemSize,
106113
}) => {
107-
const tree = React.useRef<Tree>(null);
114+
const tree = React.useRef<Tree<ExtendedData>>(null);
108115

109116
const treeWalker = React.useCallback(
110117
function*(
111118
refresh: boolean,
112-
): IterableIterator<VariableSizeNodeMetadata | string | symbol> {
119+
): IterableIterator<VariableSizeNodeData<ExtendedData> | string | symbol> {
113120
const stack: StackElement[] = [];
114121

115122
stack.push({
@@ -123,11 +130,11 @@ const TreePresenter: React.FunctionComponent<TreePresenterProps> = ({
123130

124131
const isOpened = yield refresh
125132
? {
126-
childrenCount: node.children.length,
127-
data: node.name,
128133
defaultHeight: itemSize,
129134
id,
135+
isLeaf: node.children.length === 0,
130136
isOpenByDefault: true,
137+
name: node.name,
131138
nestingLevel,
132139
}
133140
: id;
@@ -155,7 +162,7 @@ const TreePresenter: React.FunctionComponent<TreePresenterProps> = ({
155162
return (
156163
<AutoSizer disableWidth>
157164
{({height}) => (
158-
<Tree
165+
<Tree<ExtendedData>
159166
ref={tree}
160167
itemData={itemSize}
161168
treeWalker={treeWalker}

0 commit comments

Comments
 (0)