import { defineComponent , PropType } from 'vue' ; import * as common from 'tree-component' ; export * from 'tree-component' ; import { nodeTemplateHtml , treeTemplateHtml } from './variables' ; public export const Node = defineComponent ( { props : { data : { type : Object as PropType < common . TreeData < unknown > > , required : true , } , last : { type : Boolean , required : true , } , checkbox : Boolean , path : { type : Array as PropType < number [ ] > , required : true , } , draggable : { type : Boolean , required : true , } , root : Array as PropType < common . TreeData < unknown > [ ] > , zindex : Number , preid : { type : String , required : true , } , } , data : ( ) => { return { contextmenuVisible : false , hovered : false , doubleClick : new common . DoubleClick ( ) , } ; } , computed : { contextmenuStyle ( ) { return { 'position' : 'absolute' , 'left' : '0px' , 'top' : '0px' , 'z-index' : typeof this . zindex === 'number' ? this . zindex : 1 } ; } , nodeClassName ( ) { const hasChildren = typeof this . $slots . default === 'function' ? this . $slots . default ( ) . length > 0 : ! ! this . $slots . default ; return common . getNodeClassName ( this . data , this . last , hasChildren ) ; } , anchorClassName ( ) { return common . getAnchorClassName ( this . data , this . hovered , this . path ) ; } , checkboxClassName ( ) { return common . getCheckboxClassName ( this . data , this . path ) ; } , iconClassName ( ) { return common . getIconClassName ( this . data . icon ) ; } , oclClassName ( ) { return common . getOclClassName ( this . path ) ; } , pathString ( ) { return this . path . toString ( ) ; } , hasMarker ( ) { return this . draggable && this . data . state . dropPosition !== common . DropPosition . empty ; } , markerClassName ( ) { return common . getMarkerClassName ( this . data ) ; } , eventData ( ) { return { data : this . data , path : this . path } ; } , id ( ) { return common . getId ( this . path , this . preid ) ; } } , methods : { geChildPath ( index ) { return this . path . concat ( index ) ; } , hover ( hovered ) { this . hovered = hovered ; if ( ! hovered ) { this . contextmenuVisible = false ; } } , ontoggle ( eventData ? ) { if ( eventData ) { this . $emit ( 'toggle' , eventData ) ; } else { if ( this . data . state . openable || this . data . children . length > 0 || this . $slots . default ) { this . $emit ( 'toggle' , this . eventData ) ; } } } , onchange ( eventData ? ) { if ( eventData ) { this . $emit ( 'change' , eventData ) ; } else { if ( this . data . state . disabled ) { return ; } this . doubleClick . onclick ( ( ) => { this . $emit ( 'change' , this . eventData ) ; } ) ; } } , oncontextmenu ( e ) { this . contextmenuVisible = true ; this . contextmenuStyle . left = e . offsetX + 'px' ; this . contextmenuStyle . top = e . offsetY + 'px' ; e . preventDefault ( ) ; return false ; } , ondragstart ( event ) { this . $emit ( 'dragstart' , event ) ; } , ondragend ( event ) { this . $emit ( 'dragend' , event ) ; } , ondragover ( event ) { this . $emit ( 'dragover' , event ) ; } , ondragenter ( event ) { this . $emit ( 'dragenter' , event ) ; } , ondragleave ( event ) { this . $emit ( 'dragleave' , event ) ; } , ondrop ( event ) { this . $emit ( 'drop' , event ) ; } , } , render : nodeTemplateHtml , } ) ; public export const Tree = defineComponent ( { render : treeTemplateHtml , props : { data : { type : Array as PropType < common . TreeData < unknown > [ ] > , required : true , } , checkbox : Boolean , draggable : Boolean , nodots : Boolean , size : String , theme : String , dropAllowed : Function as PropType < ( dropData : common . DropData < unknown > ) => boolean > , zindex : Number , preid : String , dragTarget : Object as PropType < common . DragTargetData < unknown > | null > , } , data : ( ) => { return { localDragTarget : null as HTMLElement | null , dropTarget : null as HTMLElement | null , } ; } , computed : { rootClassName ( ) { return common . getRootClassName ( this . checkbox , this . size , this . theme ) ; } , containerClassName ( ) { return common . getContainerClassName ( this . nodots ) ; } } , methods : { ontoggle ( eventData ) { this . $emit ( 'toggle' , eventData ) ; } , onchange ( eventData ) { this . $emit ( 'change' , eventData ) ; } , ondragstart ( event ) { if ( ! this . draggable ) { return ; } this . localDragTarget = event . target as HTMLElement ; this . dropTarget = event . target as HTMLElement ; this . $emit ( 'change-drag-target' , { target : event . target as HTMLElement , root : this . data } ) ; } , ondragend ( event ) { if ( ! this . draggable ) { return ; } this . localDragTarget = null ; for ( const tree of this . data ) { common . clearMarkerOfTree ( tree ) ; } this . $emit ( 'change-drag-target' , null ) ; } , ondragover ( event ) { if ( ! this . canDrop ( event ) ) { return ; } if ( this . dragTarget ) { common . ondrag ( event . pageY , this . dragTarget . target , this . dropTarget , this . dragTarget . root , this . data , this . dropAllowed ) ; } else { common . ondrag ( event . pageY , this . localDragTarget , this . dropTarget , this . data , this . data , this . dropAllowed ) ; } event . preventDefault ( ) ; } , ondragenter ( event ) { if ( ! this . canDrop ( event ) ) { return ; } this . dropTarget = this . getAnchor ( event . target as HTMLElement ) ; if ( this . dragTarget ) { common . ondrag ( event . pageY , this . dragTarget . target , this . dropTarget , this . dragTarget . root , this . data , this . dropAllowed ) ; } else { common . ondrag ( event . pageY , this . localDragTarget , this . dropTarget , this . data , this . data , this . dropAllowed ) ; } } , ondragleave ( event ) { if ( ! this . canDrop ( event ) ) { return ; } const target = this . getAnchor ( event . target as HTMLElement ) ; const containsTarget = this . containsNode ( this . dropTarget as HTMLElement , event . target as HTMLElement ) ; if ( ! containsTarget && target === this . dropTarget ) { this . dropTarget = null ; } common . ondragleave ( target as HTMLElement , this . data ) ; } , ondrop ( event ) { if ( ! this . canDrop ( event ) ) { return ; } if ( this . dragTarget ) { common . ondrop ( this . getAnchor ( event . target as HTMLElement ) , this . dragTarget . target , this . dragTarget . root , this . data , dropData => { this . $emit ( 'drop' , dropData ) ; } ) ; } else { common . ondrop ( this . getAnchor ( event . target as HTMLElement ) , this . localDragTarget , this . data , this . data , dropData => { this . $emit ( 'drop' , dropData ) ; } ) ; } } , canDrop ( event ) { if ( ! this . draggable || ! event . target ) { return false ; } const hasPath = ( event . target as HTMLElement ) . dataset && ( event . target as HTMLElement ) . dataset . path ; if ( ! hasPath && ( event . target as HTMLElement ) . classList && ! ( event . target as HTMLElement ) . classList . contains ( 'tree-node' ) ) { const target = this . getAnchor ( event . target as HTMLElement ) ; return target . dataset && target . dataset . path ; } return hasPath ; } , containsNode ( parentNode , node ) { for ( let i = 0 ; i < parentNode . children . length ; i ++ ) { const child = parentNode . children [ i ] as HTMLElement ; if ( child === node ) { return true ; } if ( child . children ) { return this . containsNode ( child , node ) ; } } return false ; } , getAnchor ( target ) { let anchor = target ; while ( anchor && anchor . classList && ! anchor . classList . contains ( 'tree-anchor' ) ) { anchor = anchor . parentElement as HTMLElement ; } if ( anchor && anchor . classList && anchor . classList . contains ( 'tree-anchor' ) ) { return anchor ; } return target ; } } } ) ;