import { createFileList } from './FileList' ; class DataTransferItemStub implements DataTransferItem { readonly kind : DataTransferItem [ 'kind' ] ; readonly type : DataTransferItem [ 'type' ] ; private file : File | null = null ; private data : string | undefined = undefined ; constructor ( data , type ) ; constructor ( file ) ; constructor ( dataOrFile , type ? ) { if ( typeof dataOrFile === 'string' ) { this . kind = 'string' ; this . type = String ( type ) ; this . data = dataOrFile ; } else { this . kind = 'file' ; this . type = dataOrFile . type ; this . file = dataOrFile ; } } getAsFile ( ) { return this . file ; } getAsString ( callback ) { if ( typeof this . data === 'string' ) { callback ( this . data ) ; } } webkitGetAsEntry ( ) { throw new Error ( 'not implemented' ) ; } } class DataTransferItemListStub extends Array < DataTransferItem > implements DataTransferItemList { add ( data , type ) ; add ( file ) ; add ( ... args ) { const item = new DataTransferItemStub ( args [ 0 ] , args [ 1 ] ) ; this . push ( item ) ; return item ; } clear ( ) { this . splice ( 0 , this . length ) ; } remove ( index ) { this . splice ( index , 1 ) ; } } function getTypeMatcher ( type , exact ) { const [ group , sub ] = type . split ( '/' ) ; const isGroup = ! sub || sub === '*' ; return ( item ) => { return exact ? item . type === ( isGroup ? group : type ) : isGroup ? item . type . startsWith ( `${ group }/` ) : item . type === group ; } ; } class DataTransferStub implements DataTransfer { getData ( format ) { const match = this . items . find ( getTypeMatcher ( format , true ) ) ?? this . items . find ( getTypeMatcher ( format , false ) ) ; let text = '' ; match ?. getAsString ( t => { text = t ; } ) ; return text ; } setData ( format , data ) { const matchIndex = this . items . findIndex ( getTypeMatcher ( format , true ) ) ; const item = new DataTransferItemStub ( data , format ) as DataTransferItem ; if ( matchIndex >= 0 ) { this . items . splice ( matchIndex , 1 , item ) ; } else { this . items . push ( item ) ; } } clearData ( format ? ) { if ( format ) { const matchIndex = this . items . findIndex ( getTypeMatcher ( format , true ) ) ; if ( matchIndex >= 0 ) { this . items . remove ( matchIndex ) ; } } else { this . items . clear ( ) ; } } dropEffect : DataTransfer [ 'dropEffect' ] = 'none' ; effectAllowed : DataTransfer [ 'effectAllowed' ] = 'uninitialized' ; readonly items = new DataTransferItemListStub ( ) ; readonly files = createFileList ( [ ] ) ; get types ( ) { const t = [ ] ; if ( this . files . length ) { t . push ( 'Files' ) ; } this . items . forEach ( i => t . push ( i . type ) ) ; Object . freeze ( t ) ; return t ; } setDragImage ( ) { } } export function createDataTransfer ( files = [ ] ) { const dt = typeof DataTransfer === 'undefined' ? ( new DataTransferStub ( ) as DataTransfer ) : new DataTransfer ( ) ; Object . defineProperty ( dt , 'files' , { get : ( ) => createFileList ( files ) } ) ; return dt ; } export function getBlobFromDataTransferItem ( item ) { if ( item . kind === 'file' ) { return item . getAsFile ( ) as File ; } let data = '' ; item . getAsString ( s => { data = s ; } ) ; return new Blob ( [ data ] , { type : item . type } ) ; }