import React from "react" ; import { DataURLs } from "polar-shared/src/util/DataURLs" ; import { URLStr } from "polar-shared/src/util/Strings" ; import { Blobs } from "polar-shared/src/util/Blobs" ; import { Images } from "polar-shared/src/util/Images" ; export interface IPasteImageData { readonly url : URLStr ; readonly width : number ; readonly height : number ; } export interface IPasteHandlerOpts { readonly onPasteImage : ( image : IPasteImageData ) => void ; readonly onPasteError : ( err : Error ) => void ; } export type PasteImageType = 'image/webp' | 'image/png' | 'image/jpeg' | 'image/gif' | 'image/svg+xml' | 'image/avif' | 'image/apng' ; interface IPasteItemForImage { readonly kind : 'image' ; readonly type : PasteImageType ; readonly dataTransferItem : DataTransferItem ; } interface IPasteItemForUnknown { readonly kind : 'unknown' ; readonly type : string ; } export type PasteItem = IPasteItemForImage | IPasteItemForUnknown ; function toPasteItem ( item ) { switch ( item . type ) { case 'image/webp' : case 'image/png' : case 'image/jpeg' : case 'image/gif' : case 'image/svg+xml' : case 'image/avif' : case 'image/apng' : return { kind : 'image' , type : item . type , dataTransferItem : item , } ; default : return { kind : 'unknown' , type : item . type , } ; } } function isImagePaste ( pasteItems ) { for ( const pasteItem of pasteItems ) { switch ( pasteItem . kind ) { case 'image' : return true ; } } return false ; } /**
 * Clipboard paste handler that takes clipboard data given to us via an onPaste
 * handler, then handles it directly.
 */ export function usePasteHandler ( opts ) { const { onPasteImage , onPasteError } = opts ; return React . useCallback ( ( event ) => { const pasteItems = Array . from ( event . clipboardData . items ) . map ( toPasteItem ) ; async function doAsync ( ) { for ( const pasteItem of pasteItems ) { switch ( pasteItem . kind ) { case 'image' : const file = pasteItem . dataTransferItem . getAsFile ( ) ; if ( file ) { const ab = await Blobs . toArrayBuffer ( file ) ; const dataURL = DataURLs . encode ( ab , pasteItem . type ) ; const dimensions = await Images . getDimensions ( dataURL ) ; const image = { url : dataURL , ... dimensions } ; onPasteImage ( image ) ; } break ; } } } if ( isImagePaste ( pasteItems ) ) { doAsync ( ) . catch ( err => onPasteError ( err ) ) ; const unknownPasteItems = pasteItems . filter ( current => current . kind === 'unknown' ) ; if ( unknownPasteItems . length === 0 ) { event . preventDefault ( ) ; } } } , [ onPasteError , onPasteImage ] ) ; }