{"version":3,"file":"filedrop.umd.js","sources":["../lib/filedrop.ts"],"sourcesContent":["// tslint:disable-next-line:max-line-length\nfunction getMatchingItems(list: DataTransferItemList, acceptVal: string, multiple: boolean): DataTransferItem[] {\n const dataItems = Array.from(list);\n let results: DataTransferItem[];\n\n // Return the first item (or undefined) if our filter is for all files\n if (acceptVal === '') {\n results = dataItems.filter(item => item.kind === 'file');\n return (multiple) ? results : [results[0]];\n }\n\n // Split accepts values by ',' then by '/'. Trim everything & lowercase.\n const accepts = acceptVal.toLowerCase().split(',').map((accept) => {\n return accept.split('/').map(part => part.trim());\n }).filter(acceptParts => acceptParts.length === 2); // Filter invalid values\n\n const predicate = (item:DataTransferItem) => {\n if (item.kind !== 'file') return false;\n\n // 'Parse' the type.\n const [typeMain, typeSub] = item.type.toLowerCase().split('/').map(s => s.trim());\n\n for (const [acceptMain, acceptSub] of accepts) {\n // Look for an exact match, or a partial match if * is accepted, eg image/*.\n if (typeMain === acceptMain && (acceptSub === '*' || typeSub === acceptSub)) {\n return true;\n }\n }\n return false;\n };\n\n results = results = dataItems.filter(predicate);\n if (multiple === false) {\n results = [results[0]];\n }\n\n return results;\n}\n\nfunction getFileData(data: DataTransfer, accept: string, multiple: boolean): File[] {\n const dragDataItems = getMatchingItems(data.items, accept, multiple);\n const files: File[] = [];\n\n // This is because Map doesn't like the null type returned by getAsFile\n dragDataItems.forEach((item) => {\n const file = item.getAsFile();\n if (file === null) return;\n files.push(file);\n });\n\n return files;\n}\n\n// Safari and Edge don't quite support extending Event, this works around it.\nfunction fixExtendedEvent(instance: Event, type: Function) {\n if (!(instance instanceof type)) {\n Object.setPrototypeOf(instance, type.prototype);\n }\n}\n\ninterface FileDropEventInit extends EventInit {\n action: FileDropAccept;\n files: File[];\n}\n\ntype FileDropAccept = 'drop' | 'paste';\n\nexport class FileDropEvent extends Event {\n private _action: FileDropAccept;\n private _files: File[];\n constructor(typeArg: string, eventInitDict: FileDropEventInit) {\n super(typeArg, eventInitDict);\n fixExtendedEvent(this, FileDropEvent);\n this._files = eventInitDict.files;\n this._action = eventInitDict.action;\n }\n\n get action() {\n return this._action;\n }\n\n get files() {\n return this._files;\n }\n}\n\n/*\n Example Usage.\n \n [everything in here is a drop target.]\n \n\n dropElement.addEventListener('filedrop', (event) => console.log(event.detail))\n*/\nexport class FileDropElement extends HTMLElement {\n\n private _dragEnterCount = 0;\n\n constructor() {\n super();\n\n // Bind\n this._onDragEnter = this._onDragEnter.bind(this);\n this._onDragLeave = this._onDragLeave.bind(this);\n this._onDrop = this._onDrop.bind(this);\n this._onPaste = this._onPaste.bind(this);\n\n this.addEventListener('dragover', event => event.preventDefault());\n this.addEventListener('drop', this._onDrop);\n this.addEventListener('dragenter', this._onDragEnter);\n this.addEventListener('dragend', () => this._reset());\n this.addEventListener('dragleave', this._onDragLeave);\n this.addEventListener('paste', this._onPaste);\n }\n\n get accept() {\n return this.getAttribute('accept') || '';\n }\n\n set accept(val: string) {\n this.setAttribute('accept', val);\n }\n\n get multiple() : string | null {\n return this.getAttribute('multiple');\n }\n\n set multiple(val: string | null) {\n this.setAttribute('multiple', val || '');\n }\n\n private _onDragEnter(event: DragEvent) {\n this._dragEnterCount += 1;\n if (this._dragEnterCount > 1) return;\n if (event.dataTransfer === null) {\n this.classList.add('drop-invalid');\n return;\n }\n\n // We don't have data, attempt to get it and if it matches, set the correct state.\n const items = event.dataTransfer.items;\n const matchingFiles = getMatchingItems(items, this.accept, (this.multiple !== null));\n const validDrop: boolean = event.dataTransfer && event.dataTransfer.items.length ?\n (matchingFiles[0] !== undefined) :\n // Safari doesn't give file information on drag enter, so the best we\n // can do is return valid.\n true;\n\n if (validDrop) {\n this.classList.add('drop-valid');\n } else {\n this.classList.add('drop-invalid');\n }\n }\n\n private _onDragLeave() {\n this._dragEnterCount -= 1;\n if (this._dragEnterCount === 0) {\n this._reset();\n }\n }\n\n private _onDrop(event: DragEvent) {\n event.preventDefault();\n if (event.dataTransfer === null) return;\n this._reset();\n const action = 'drop';\n const files = getFileData(event.dataTransfer, this.accept, (this.multiple !== null));\n if (files === undefined) return;\n\n this.dispatchEvent(new FileDropEvent('filedrop', { action, files }));\n }\n\n private _onPaste(event: ClipboardEvent) {\n const action = 'paste';\n if(!event.clipboardData) return;\n const files = getFileData(event.clipboardData, this.accept, (this.multiple !== undefined));\n if (files === undefined) return;\n\n this.dispatchEvent(new FileDropEvent('filedrop', { action, files }));\n }\n\n private _reset() {\n this._dragEnterCount = 0;\n this.classList.remove('drop-valid');\n this.classList.remove('drop-invalid');\n }\n}\n\ncustomElements.define('file-drop', FileDropElement);\n"],"names":["list","acceptVal","multiple","dataItems","Array","from","results","filter","item","kind","accepts","toLowerCase","split","map","accept","part","trim","acceptParts","length","typeMain","typeSub","type","s","acceptMain","acceptSub","data","files","getMatchingItems","items","forEach","file","getAsFile","push","Event","[object Object]","typeArg","eventInitDict","instance","super","this","FileDropEvent","Object","setPrototypeOf","prototype","_files","_action","action","HTMLElement","_onDragEnter","bind","_onDragLeave","_onDrop","_onPaste","addEventListener","event","preventDefault","_reset","getAttribute","val","setAttribute","_dragEnterCount","dataTransfer","classList","add","matchingFiles","undefined","getFileData","dispatchEvent","clipboardData","remove","customElements","define","FileDropElement"],"mappings":"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"}