import { CSSResultArray , html , SpectrumElement , TemplateResult , } from '@spectrum-web-components/base' ; import { property } from '@spectrum-web-components/base/src/decorators.js' ; import dropzoneStyles from './dropzone.css.js' ; export type DropzoneEventDetail = DragEvent ; export type DropEffects = 'copy' | 'move' | 'link' | 'none' ; element slot fires fires fires fires export class Dropzone extends SpectrumElement { public static get styles ( ) : CSSResultArray { return [ dropzoneStyles ] ; } attr type { 'copy' | 'move' | 'link' | 'none' } public get dropEffect ( ) : DropEffects { return this . _dropEffect ; } public set dropEffect ( value ) { if ( [ 'copy' , 'move' , 'link' , 'none' ] . includes ( value ) ) { this . _dropEffect = value ; } } private _dropEffect : DropEffects = 'copy' ; @ property ( { type : Boolean , reflect : true , attribute : 'dragged' } ) public isDragged = false ; private debouncedDragLeave : number | null = null ; public connectedCallback ( ) { super . connectedCallback ( ) ; this . addEventListener ( 'drop' , this . onDrop ) ; this . addEventListener ( 'dragover' , this . onDragOver ) ; this . addEventListener ( 'dragleave' , this . onDragLeave ) ; } public disconnectedCallback ( ) { super . disconnectedCallback ( ) ; this . removeEventListener ( 'drop' , this . onDrop ) ; this . removeEventListener ( 'dragover' , this . onDragOver ) ; this . removeEventListener ( 'dragleave' , this . onDragLeave ) ; } public onDragOver ( event ) { const shouldAcceptEvent = new CustomEvent ( 'sp-dropzone-should-accept' , { bubbles : true , cancelable : true , composed : true , detail : event , } ) ; const shouldAccept = this . dispatchEvent ( shouldAcceptEvent ) ; if ( ! event . dataTransfer ) { return ; } if ( ! shouldAccept ) { event . dataTransfer . dropEffect = 'none' ; return ; } event . preventDefault ( ) ; this . clearDebouncedDragLeave ( ) ; this . isDragged = true ; event . dataTransfer . dropEffect = this . dropEffect ; const dragOverEvent = new CustomEvent ( 'sp-dropzone-dragover' , { bubbles : true , composed : true , detail : event , } ) ; this . dispatchEvent ( dragOverEvent ) ; } public onDragLeave ( event ) { this . clearDebouncedDragLeave ( ) ; this . debouncedDragLeave = window . setTimeout ( ( ) => { this . isDragged = false ; const dragLeave = new CustomEvent ( 'sp-dropzone-dragleave' , { bubbles : true , composed : true , detail : event , } ) ; this . dispatchEvent ( dragLeave ) ; } , 100 ) ; } public onDrop ( event ) { event . preventDefault ( ) ; this . clearDebouncedDragLeave ( ) ; this . isDragged = false ; const dropEvent = new CustomEvent ( 'sp-dropzone-drop' , { bubbles : true , composed : true , detail : event , } ) ; this . dispatchEvent ( dropEvent ) ; } protected render ( ) { return html `
            <slot></slot>
        ` ; } protected clearDebouncedDragLeave ( ) { if ( this . debouncedDragLeave ) { clearTimeout ( this . debouncedDragLeave ) ; this . debouncedDragLeave = null ; } } } declare global { interface GlobalEventHandlersEventMap { 'sp-dropzone:should-accept' : CustomEvent < DragEvent > ; 'sp-dropzone:dragover' : CustomEvent < DragEvent > ; 'sp-dropzone:dragleave' : CustomEvent < DragEvent > ; 'sp-dropzone:drop' : CustomEvent < DragEvent > ; } }