@@ -12,6 +12,7 @@ import {
1212 useRef ,
1313 useState
1414} from "react" ;
15+ import { ObjectItem , Option } from "mendix" ;
1516
1617import { OpenNodeOnEnum , ShowIconEnum } from "../../typings/TreeNodeProps" ;
1718
@@ -20,20 +21,22 @@ import { useAnimatedTreeNodeContentHeight } from "./hooks/useAnimatedHeight";
2021import { TreeNodeFocusChangeHandler , useTreeNodeBranchKeyboardHandler } from "./hooks/TreeNodeAccessibility" ;
2122
2223import { TreeNodeHeaderIcon } from "./HeaderIcon" ;
23- import { TreeNodeItem , TreeNodeState } from "./TreeNode" ;
24+ import { TreeNode as TreeNodeComponent , TreeNodeItem , TreeNodeProps , TreeNodeState } from "./TreeNode" ;
2425import { TreeNodeBranchContext , TreeNodeBranchContextProps } from "./TreeNodeBranchContext" ;
2526
2627export interface TreeNodeBranchProps {
28+ item : TreeNodeItem ;
2729 animateTreeNodeContent : boolean ;
2830 children : ReactNode ;
29- headerContent : ReactNode ;
3031 iconPlacement : ShowIconEnum ;
31- id : TreeNodeItem [ "id" ] ;
32- isUserDefinedLeafNode : boolean ;
3332 openNodeOn : OpenNodeOnEnum ;
3433 startExpanded : boolean ;
3534 changeFocus : TreeNodeFocusChangeHandler ;
3635 renderHeaderIcon : TreeNodeHeaderIcon ;
36+ fetchChildren : ( item ?: Option < ObjectItem > ) => Promise < TreeNodeItem [ ] > ;
37+ appendChildren : ( items : TreeNodeItem [ ] , parent : TreeNodeItem ) => void ;
38+ treeNodeProps : TreeNodeProps ;
39+ isInfiniteTreeNodesEnabled : boolean ;
3740}
3841
3942export const treeNodeBranchUtils = {
@@ -43,23 +46,28 @@ export const treeNodeBranchUtils = {
4346} ;
4447
4548export function TreeNodeBranch ( {
49+ item,
4650 animateTreeNodeContent : animateTreeNodeContentProp ,
4751 changeFocus,
4852 children,
49- headerContent,
5053 iconPlacement,
51- id,
52- isUserDefinedLeafNode,
5354 openNodeOn,
5455 renderHeaderIcon,
55- startExpanded
56+ startExpanded,
57+ fetchChildren,
58+ appendChildren,
59+ isInfiniteTreeNodesEnabled,
60+ treeNodeProps
5661} : TreeNodeBranchProps ) : ReactElement {
5762 const { level : currentContextLevel } = useContext ( TreeNodeBranchContext ) ;
63+ const { id, headerContent, isUserDefinedLeafNode } = item ;
5864
5965 const treeNodeBranchRef = useRef < HTMLLIElement > ( null ) ;
6066 const treeNodeBranchBody = useRef < HTMLDivElement > ( null ) ;
6167
62- const [ isActualLeafNode , setIsActualLeafNode ] = useState < boolean > ( isUserDefinedLeafNode || ! children ) ;
68+ const [ isActualLeafNode , setIsActualLeafNode ] = useState < boolean > (
69+ isUserDefinedLeafNode || ( ! children && ! isInfiniteTreeNodesEnabled )
70+ ) ;
6371 const [ treeNodeState , setTreeNodeState ] = useState < TreeNodeState > (
6472 startExpanded ? TreeNodeState . EXPANDED : TreeNodeState . COLLAPSED_WITH_JS
6573 ) ;
@@ -92,30 +100,55 @@ export function TreeNodeBranch({
92100 ) ;
93101 } , [ ] ) ;
94102
103+ const updateTreeNodeState = useCallback ( ( ) => {
104+ setTreeNodeState ( treeNodeState => {
105+ if ( treeNodeState === TreeNodeState . LOADING ) {
106+ // TODO:
107+ return treeNodeState ;
108+ }
109+ if ( treeNodeState === TreeNodeState . COLLAPSED_WITH_JS ) {
110+ return TreeNodeState . LOADING ;
111+ }
112+ if ( treeNodeState === TreeNodeState . COLLAPSED_WITH_CSS ) {
113+ return TreeNodeState . EXPANDED ;
114+ }
115+ return TreeNodeState . COLLAPSED_WITH_CSS ;
116+ } ) ;
117+ } , [ ] ) ;
118+
95119 const toggleTreeNodeContent = useCallback < ReactEventHandler < HTMLElement > > (
96120 event => {
97121 if ( eventTargetIsNotCurrentBranch ( event ) ) {
98122 return ;
99123 }
100124
101- if ( ! isActualLeafNode ) {
102- captureElementHeight ( ) ;
103- setTreeNodeState ( treeNodeState => {
104- if ( treeNodeState === TreeNodeState . LOADING ) {
105- // TODO:
106- return treeNodeState ;
107- }
108- if ( treeNodeState === TreeNodeState . COLLAPSED_WITH_JS ) {
109- return TreeNodeState . LOADING ;
125+ // load children for infinite tree nodes
126+ if ( isInfiniteTreeNodesEnabled ) {
127+ fetchChildren ( item ) . then ( result => {
128+ if ( Array . isArray ( result ) && result . length > 0 ) {
129+ // append children to the localized item
130+ appendChildren ( result , item ) ;
131+ } else {
132+ setIsActualLeafNode ( true ) ;
110133 }
111- if ( treeNodeState === TreeNodeState . COLLAPSED_WITH_CSS ) {
112- return TreeNodeState . EXPANDED ;
113- }
114- return TreeNodeState . COLLAPSED_WITH_CSS ;
115134 } ) ;
116135 }
136+
137+ if ( ! isActualLeafNode ) {
138+ captureElementHeight ( ) ;
139+ updateTreeNodeState ( ) ;
140+ }
117141 } ,
118- [ captureElementHeight , eventTargetIsNotCurrentBranch , isActualLeafNode ]
142+ [
143+ captureElementHeight ,
144+ eventTargetIsNotCurrentBranch ,
145+ isActualLeafNode ,
146+ updateTreeNodeState ,
147+ fetchChildren ,
148+ item ,
149+ isInfiniteTreeNodesEnabled ,
150+ appendChildren
151+ ]
119152 ) ;
120153
121154 const onHeaderKeyDown = useTreeNodeBranchKeyboardHandler (
@@ -143,8 +176,8 @@ export function TreeNodeBranch({
143176 } , [ animateTreeNodeContent , animateTreeNodeContentProp , treeNodeState ] ) ;
144177
145178 useEffect ( ( ) => {
146- setIsActualLeafNode ( isUserDefinedLeafNode || ! children ) ;
147- } , [ children , isUserDefinedLeafNode ] ) ;
179+ setIsActualLeafNode ( isUserDefinedLeafNode || ( ! children && ! isInfiniteTreeNodesEnabled ) ) ;
180+ } , [ children , isUserDefinedLeafNode , isInfiniteTreeNodesEnabled ] ) ;
148181
149182 useEffect ( ( ) => {
150183 if ( treeNodeState === TreeNodeState . LOADING ) {
@@ -199,7 +232,11 @@ export function TreeNodeBranch({
199232 ref = { treeNodeBranchBody }
200233 onTransitionEnd = { cleanupAnimation }
201234 >
202- { children }
235+ { isInfiniteTreeNodesEnabled && item . children && item . children . length > 0 ? (
236+ < TreeNodeComponent { ...treeNodeProps } items = { item . children || [ ] } />
237+ ) : (
238+ children
239+ ) }
203240 </ div >
204241 </ TreeNodeBranchContext . Provider >
205242 ) }
0 commit comments