1- import cls from 'classnames ' ;
1+ import throttle from 'lodash/throttle ' ;
22import React , { useCallback , useRef , useEffect , useState } from 'react' ;
33import CtxMenuTrigger from 'react-ctxmenu-trigger' ;
44
@@ -25,6 +25,7 @@ export const BasicRecycleTree: React.FC<IBasicRecycleTreeProps> = ({
2525 itemHeight = 22 ,
2626 itemClassname,
2727 indent,
28+ baseIndent,
2829 containerClassname,
2930 onClick,
3031 onContextMenu,
@@ -38,6 +39,8 @@ export const BasicRecycleTree: React.FC<IBasicRecycleTreeProps> = ({
3839 onReady,
3940 contextMenus,
4041 contextMenuActuator,
42+ treeName,
43+ getItemClassName,
4144} ) => {
4245 const [ showMenus , setShowMenus ] = useState < {
4346 show : boolean ;
@@ -49,35 +52,46 @@ export const BasicRecycleTree: React.FC<IBasicRecycleTreeProps> = ({
4952 } > ( { show : false } ) ;
5053 const [ menubarItems , setMenubarItems ] = useState < IBasicTreeMenu [ ] > ( [ ] ) ;
5154 const [ model , setModel ] = useState < BasicTreeModel | undefined > ( ) ;
52- const treeService = useRef < BasicTreeService > ( new BasicTreeService ( treeData , resolveChildren , sortComparator ) ) ;
55+ const treeService = useRef < BasicTreeService > ( ) ;
5356 const treeHandle = useRef < IRecycleTreeHandle > ( ) ;
5457 const wrapperRef : React . RefObject < HTMLDivElement > = React . createRef ( ) ;
5558
5659 const renderTreeNode = useCallback (
57- ( props : INodeRendererWrapProps ) => (
58- < BasicTreeNodeRenderer
59- item = { props . item as any }
60- itemType = { props . itemType }
61- itemHeight = { itemHeight }
62- indent = { indent }
63- className = { itemClassname }
64- inlineMenus = { inlineMenus }
65- inlineMenuActuator = { inlineMenuActuator }
66- onClick = { handleItemClick }
67- onDbClick = { handleItemDbClick }
68- onContextMenu = { handleContextMenu }
69- onTwistierClick = { handleTwistierClick }
70- decorations = { treeService . current . decorations . getDecorations ( props . item as ITreeNodeOrCompositeTreeNode ) }
71- />
72- ) ,
73- [ ] ,
60+ ( props : INodeRendererWrapProps ) => {
61+ let _indent : number | undefined ;
62+ if ( baseIndent ) {
63+ _indent = baseIndent ;
64+ }
65+ if ( indent ) {
66+ _indent = ( _indent ?? 0 ) + indent ;
67+ }
68+
69+ return (
70+ < BasicTreeNodeRenderer
71+ item = { props . item as any }
72+ itemType = { props . itemType }
73+ itemHeight = { itemHeight }
74+ indent = { _indent }
75+ className = { getItemClassName ?.( props . item as any ) ?? itemClassname }
76+ inlineMenus = { inlineMenus }
77+ inlineMenuActuator = { inlineMenuActuator }
78+ onClick = { handleItemClick }
79+ onDbClick = { handleItemDbClick }
80+ onContextMenu = { handleContextMenu }
81+ onTwistierClick = { handleTwistierClick }
82+ decorations = { treeService . current ?. decorations . getDecorations ( props . item as ITreeNodeOrCompositeTreeNode ) }
83+ />
84+ ) ;
85+ } ,
86+ [ model ] ,
7487 ) ;
7588
7689 useEffect ( ( ) => {
77- ensureLoaded ( ) ;
78- const disposable = treeService . current . onDidUpdateTreeModel ( async ( model ?: BasicTreeModel ) => {
79- await model ?. ensureReady ;
80- setModel ( model ) ;
90+ treeService . current = new BasicTreeService ( treeData , resolveChildren , sortComparator , {
91+ treeName,
92+ } ) ;
93+ const disposable = treeService . current ?. onDidUpdateTreeModel ( ( model ?: BasicTreeModel ) => {
94+ ensureLoaded ( model ) ;
8195 } ) ;
8296 const handleBlur = ( ) => {
8397 treeService . current ?. enactiveFocusedDecoration ( ) ;
@@ -91,30 +105,51 @@ export const BasicRecycleTree: React.FC<IBasicRecycleTreeProps> = ({
91105 } ;
92106 } , [ ] ) ;
93107
94- const ensureLoaded = async ( ) => {
95- const model = treeService . current . model ;
108+ useEffect ( ( ) => {
109+ treeService . current ?. updateTreeData ( treeData ) ;
110+ } , [ treeData ] ) ;
111+
112+ const ensureLoaded = async ( model ?: BasicTreeModel ) => {
96113 if ( model ) {
97114 await model . ensureReady ;
98115 }
99116 setModel ( model ) ;
100117 } ;
101118
102- const handleTreeReady = useCallback ( ( handle : IRecycleTreeHandle ) => {
103- if ( onReady ) {
104- onReady ( handle ) ;
119+ const selectItem = async ( item : BasicCompositeTreeNode | BasicTreeNode ) => {
120+ treeService . current ?. activeFocusedDecoration ( item ) ;
121+ if ( BasicCompositeTreeNode . is ( item ) ) {
122+ toggleDirectory ( item ) ;
105123 }
106- treeHandle . current = handle ;
107- } , [ ] ) ;
124+ } ;
125+
126+ const handleTreeReady = useCallback (
127+ ( handle : IRecycleTreeHandle ) => {
128+ if ( onReady ) {
129+ onReady ( {
130+ ...handle ,
131+ selectItem,
132+ focusItem : async ( nodePath : string ) => {
133+ const path = `/${ treeName } /${ nodePath } ` ;
134+ await model ?. ensureReady ;
135+ const node = ( await handle . ensureVisible ( path , 'auto' , true ) ) as BasicCompositeTreeNode ;
136+ if ( node ) {
137+ treeService . current ?. activeFocusedDecoration ( node ) ;
138+ }
139+ } ,
140+ } ) ;
141+ }
142+ treeHandle . current = handle ;
143+ } ,
144+ [ treeService . current ] ,
145+ ) ;
108146
109147 const handleItemClick = useCallback (
110148 ( event : React . MouseEvent , item : BasicCompositeTreeNode | BasicTreeNode ) => {
111- treeService . current ?. activeFocusedDecoration ( item ) ;
149+ selectItem ( item ) ;
112150 if ( onClick ) {
113151 onClick ( event , item ) ;
114152 }
115- if ( BasicCompositeTreeNode . is ( item ) ) {
116- toggleDirectory ( item ) ;
117- }
118153 } ,
119154 [ onClick ] ,
120155 ) ;
@@ -198,7 +233,7 @@ export const BasicRecycleTree: React.FC<IBasicRecycleTreeProps> = ({
198233 const handleOuterContextMenu = useCallback (
199234 ( event : React . MouseEvent , item ?: BasicCompositeTreeNode | BasicTreeNode ) => {
200235 if ( onContextMenu ) {
201- onContextMenu ( event ) ;
236+ onContextMenu ( event , item ) ;
202237 }
203238 } ,
204239 [ ] ,
@@ -270,7 +305,8 @@ export const BasicRecycleTree: React.FC<IBasicRecycleTreeProps> = ({
270305 itemHeight = { itemHeight }
271306 model = { model }
272307 onReady = { handleTreeReady }
273- className = { cls ( containerClassname ) }
308+ className = { containerClassname }
309+ leaveBottomBlank
274310 >
275311 { renderTreeNode }
276312 </ RecycleTree >
0 commit comments