11import cls from 'classnames' ;
2- import React from 'react' ;
2+ import React , { CSSProperties , FC , MouseEvent , ReactNode , useCallback , useEffect , useState , DragEvent } from 'react' ;
33
44import { INodeRendererProps , ClasslistComposite , PromptHandle , TreeNodeType } from '@opensumi/ide-components' ;
55import { Loading } from '@opensumi/ide-components' ;
@@ -19,23 +19,21 @@ export interface ITreeViewNodeProps {
1919 defaultLeftPadding ?: number ;
2020 leftPadding ?: number ;
2121 decorations ?: ClasslistComposite ;
22- onTwistierClick ?: (
23- ev : React . MouseEvent ,
24- item : ExtensionTreeNode | ExtensionCompositeTreeNode ,
25- type : TreeNodeType ,
26- ) => void ;
27- onClick : ( ev : React . MouseEvent , item : ExtensionTreeNode | ExtensionCompositeTreeNode , type : TreeNodeType ) => void ;
28- onContextMenu ?: (
29- ev : React . MouseEvent ,
30- item : ExtensionTreeNode | ExtensionCompositeTreeNode ,
31- type : TreeNodeType ,
32- ) => void ;
22+ onTwistierClick ?: ( ev : MouseEvent , item : ExtensionTreeNode | ExtensionCompositeTreeNode , type : TreeNodeType ) => void ;
23+ onClick : ( ev : MouseEvent , item : ExtensionTreeNode | ExtensionCompositeTreeNode , type : TreeNodeType ) => void ;
24+ onContextMenu ?: ( ev : MouseEvent , item : ExtensionTreeNode | ExtensionCompositeTreeNode , type : TreeNodeType ) => void ;
25+ onDragStart ?: ( ev : MouseEvent , item : ExtensionTreeNode | ExtensionCompositeTreeNode ) => void ;
26+ onDragEnter ?: ( ev : MouseEvent , item : ExtensionTreeNode | ExtensionCompositeTreeNode ) => void ;
27+ onDrop ?: ( ev : MouseEvent , item : ExtensionTreeNode | ExtensionCompositeTreeNode ) => void ;
28+ onDragOver ?: ( ev : MouseEvent , item : ExtensionTreeNode | ExtensionCompositeTreeNode ) => void ;
29+ onDragLeave ?: ( ev : MouseEvent , item : ExtensionTreeNode | ExtensionCompositeTreeNode ) => void ;
3330 decorationService : IDecorationsService ;
31+ draggable : boolean ;
3432}
3533
3634export type TreeViewNodeRenderedProps = ITreeViewNodeProps & INodeRendererProps ;
3735
38- export const TreeViewNode : React . FC < TreeViewNodeRenderedProps > = ( {
36+ export const TreeViewNode : FC < TreeViewNodeRenderedProps > = ( {
3937 item,
4038 onClick,
4139 onContextMenu,
@@ -46,10 +44,16 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
4644 defaultLeftPadding = 8 ,
4745 treeViewId,
4846 decorationService,
47+ draggable,
48+ onDragStart,
49+ onDragEnter,
50+ onDragLeave,
51+ onDragOver,
52+ onDrop,
4953} : TreeViewNodeRenderedProps ) => {
50- const [ decoration , setDecoration ] = React . useState ( item . uri && decorationService . getDecoration ( item . uri , false ) ) ;
54+ const [ decoration , setDecoration ] = useState ( item . uri && decorationService . getDecoration ( item . uri , false ) ) ;
5155
52- React . useEffect ( ( ) => {
56+ useEffect ( ( ) => {
5357 const disposable = decorationService . onDidChangeDecorations ( ( e ) => {
5458 if ( item . uri && e . affectsResource ( item . uri ) ) {
5559 setDecoration ( decorationService . getDecoration ( item . uri , false ) ) ;
@@ -62,30 +66,74 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
6266
6367 const themeService = useInjectable < IThemeService > ( IThemeService ) ;
6468
65- const handleClick = ( ev : React . MouseEvent ) => {
66- if ( itemType === TreeNodeType . TreeNode || itemType === TreeNodeType . CompositeTreeNode ) {
67- onClick ( ev , item , itemType ) ;
68- }
69- } ;
70-
71- const handlerTwistierClick = ( ev : React . MouseEvent ) => {
72- if ( itemType === TreeNodeType . TreeNode || itemType === TreeNodeType . CompositeTreeNode ) {
73- if ( onTwistierClick ) {
74- onTwistierClick ( ev , item , itemType ) ;
75- } else {
69+ const handleClick = useCallback (
70+ ( ev : MouseEvent ) => {
71+ if ( itemType === TreeNodeType . TreeNode || itemType === TreeNodeType . CompositeTreeNode ) {
7672 onClick ( ev , item , itemType ) ;
7773 }
78- }
79- } ;
74+ } ,
75+ [ item , itemType , onClick ] ,
76+ ) ;
8077
81- const handleContextMenu = ( ev : React . MouseEvent ) => {
82- if ( ev . nativeEvent . which === 0 || ! onContextMenu ) {
83- return ;
84- }
85- if ( itemType === TreeNodeType . TreeNode || itemType === TreeNodeType . CompositeTreeNode ) {
86- onContextMenu ( ev , item , itemType ) ;
87- }
88- } ;
78+ const handlerTwistierClick = useCallback (
79+ ( ev : MouseEvent ) => {
80+ if ( itemType === TreeNodeType . TreeNode || itemType === TreeNodeType . CompositeTreeNode ) {
81+ if ( onTwistierClick ) {
82+ onTwistierClick ( ev , item , itemType ) ;
83+ } else {
84+ onClick ( ev , item , itemType ) ;
85+ }
86+ }
87+ } ,
88+ [ itemType , onTwistierClick , onClick ] ,
89+ ) ;
90+
91+ const handleContextMenu = useCallback (
92+ ( ev : MouseEvent ) => {
93+ if ( ev . nativeEvent . which === 0 || ! onContextMenu ) {
94+ return ;
95+ }
96+ if ( itemType === TreeNodeType . TreeNode || itemType === TreeNodeType . CompositeTreeNode ) {
97+ onContextMenu ( ev , item , itemType ) ;
98+ }
99+ } ,
100+ [ item , itemType , onContextMenu ] ,
101+ ) ;
102+
103+ const handleDragStart = useCallback (
104+ ( event : DragEvent ) => {
105+ onDragStart && onDragStart ( event , item ) ;
106+ } ,
107+ [ item , onDragStart ] ,
108+ ) ;
109+
110+ const handleDragEnter = useCallback (
111+ ( event : DragEvent ) => {
112+ onDragEnter && onDragEnter ( event , item ) ;
113+ } ,
114+ [ item , onDragEnter ] ,
115+ ) ;
116+
117+ const handleDragLeave = useCallback (
118+ ( event : DragEvent ) => {
119+ onDragLeave && onDragLeave ( event , item ) ;
120+ } ,
121+ [ item , onDragLeave ] ,
122+ ) ;
123+
124+ const handleDragOver = useCallback (
125+ ( event : DragEvent ) => {
126+ onDragOver && onDragOver ( event , item ) ;
127+ } ,
128+ [ item , onDragOver ] ,
129+ ) ;
130+
131+ const handleDrop = useCallback (
132+ ( event : DragEvent ) => {
133+ onDrop && onDrop ( event , item ) ;
134+ } ,
135+ [ item , onDrop ] ,
136+ ) ;
89137
90138 const isDirectory = itemType === TreeNodeType . CompositeTreeNode ;
91139 const paddingLeft = isDirectory
@@ -96,7 +144,7 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
96144 height : TREE_VIEW_NODE_HEIGHT ,
97145 lineHeight : `${ TREE_VIEW_NODE_HEIGHT } px` ,
98146 paddingLeft,
99- } as React . CSSProperties ;
147+ } as CSSProperties ;
100148
101149 const renderFolderToggle = ( node : ExtensionCompositeTreeNode | PromptHandle , clickHandler : any ) => {
102150 if ( decorations && decorations ?. classlist . indexOf ( styles . mod_loading ) > - 1 ) {
@@ -119,7 +167,7 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
119167 const renderDisplayName = ( node : ExtensionCompositeTreeNode | ExtensionTreeNode ) => {
120168 const displayName = ( ) => {
121169 if ( node . highlights ) {
122- let hightlightSnaps : React . ReactNode [ ] = [ ] ;
170+ let hightlightSnaps : ReactNode [ ] = [ ] ;
123171 let endIndex = 0 ;
124172 const hightlights = node . highlights . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] ) ;
125173 hightlightSnaps = hightlights . map ( ( highlight , index : number ) => {
@@ -213,11 +261,16 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
213261 key = { item . id }
214262 onClick = { handleClick }
215263 onContextMenu = { handleContextMenu }
264+ onDragStart = { handleDragStart }
265+ onDragOver = { handleDragOver }
266+ onDragEnter = { handleDragEnter }
267+ onDragLeave = { handleDragLeave }
268+ onDrop = { handleDrop }
216269 title = { getItemTooltip ( ) }
217270 className = { cls ( styles . tree_view_node , decorations ? decorations . classlist : null ) }
218271 data-id = { item . id }
219272 style = { fileTreeNodeStyle }
220- draggable = { itemType === TreeNodeType . TreeNode || itemType === TreeNodeType . CompositeTreeNode }
273+ draggable = { draggable }
221274 >
222275 < div className = { cls ( styles . tree_view_node_content ) } >
223276 { renderTwice ( item ) }
0 commit comments