-
-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathnode-view.tsx
122 lines (106 loc) · 3.28 KB
/
node-view.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import React, { ReactElement, useCallback, useEffect, useState } from 'react';
import { Pressable, VirtualizedList } from 'react-native';
import { useNodesContext } from '../nodes-context-provider';
import { Node } from './types';
export interface IProps {
getChildrenName: (item: Node) => string;
node: Node;
level: number;
onNodePressed?: (item: Node) => void;
renderNode: (item: Node, level: number, isLastLevel: boolean) => ReactElement;
renderChildrenNode?: (item: Node) => ReactElement;
extraData?: any;
keepOpenedState?: boolean;
initialNumToRender?: number;
}
const NodeView: React.FC<IProps> = React.memo(
({
renderNode,
extraData,
level,
getChildrenName,
node,
onNodePressed,
keepOpenedState,
initialNumToRender,
}) => {
const { openedNodes, setOpenNode } = useNodesContext();
const [_node, setNode]: [Node, any] = useState({
...node,
opened:
keepOpenedState && openedNodes[node._internalId]
? !!openedNodes[node._internalId]
: !!node.opened,
});
useEffect(() => {
setNode({
...node,
opened: _node.opened,
});
}, [node, _node.opened]);
const _onNodePressed = useCallback(() => {
if (keepOpenedState) {
setOpenNode &&
setOpenNode({
internalId: _node._internalId,
opened: !_node.opened,
});
}
setNode({
..._node,
opened: !_node.opened,
});
if (onNodePressed) {
onNodePressed(_node);
}
}, [_node, keepOpenedState, onNodePressed, setOpenNode]);
const renderChildren = useCallback(
(item: Node, _level: number): ReactElement => (
<NodeView
getChildrenName={getChildrenName}
node={item}
level={_level + 1}
extraData={extraData}
onNodePressed={onNodePressed}
renderNode={renderNode}
keepOpenedState={keepOpenedState}
/>
),
[extraData, getChildrenName, onNodePressed, renderNode, keepOpenedState],
);
const renderItem = useCallback(
({ item }: { item: Node }) => renderChildren(item, level),
[renderChildren, level],
);
const getItem = useCallback((data, index) => data && data[index], []);
const getItemCount = useCallback((data) => data?.length, []);
const keyExtractor = useCallback((item: Node) => item._internalId, []);
const nodeChildrenName = getChildrenName(_node);
const nodeChildren: [] = _node[nodeChildrenName];
const isNodeOpened =
(keepOpenedState && openedNodes[node._internalId]) || _node.opened;
return (
<>
{!_node.hidden ? (
<Pressable onPress={_onNodePressed}>
{renderNode(_node, level, !nodeChildren || !nodeChildren.length)}
</Pressable>
) : null}
{isNodeOpened && nodeChildren ? (
<VirtualizedList
data={nodeChildren}
getItemCount={getItemCount}
getItem={getItem}
renderItem={renderItem}
extraData={extraData}
keyExtractor={keyExtractor}
listKey={node._internalId}
initialNumToRender={initialNumToRender}
/>
) : null}
</>
);
},
);
NodeView.displayName = 'NodeView';
export { NodeView };