{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-upload/src/filereader.js","webpack:///./node_modules/@ckeditor/ckeditor5-upload/src/filerepository.js","webpack:///./node_modules/@ckeditor/ckeditor5-upload/src/ui/filedialogbuttonview.js"],"names":["FileReader","_this","this","Object","classCallCheck","reader","window","_reader","_data","undefined","set","onprogress","evt","loaded","error","file","_this2","total","size","Promise","resolve","reject","onload","result","onerror","onabort","readAsDataURL","abort","mix","ObservableMixin","FileRepository","loaders","Collection","on","_updatePendingAction","_loadersMap","Map","_pendingAction","bind","to","uploaded","fileOrPromise","get","createUploadAdapter","logWarning","loader","FileLoader","add","then","catch","_step","aggregatedUploaded","_iterator","_createForOfIteratorHelper","s","n","done","value","err","e","f","_step2","aggregatedTotal","_iterator2","uploadTotal","fileOrPromiseOrLoader","_this3","getLoader","_destroy","remove","forEach","key","delete","pendingActions","editor","plugins","PendingActions","length","t","getMessage","concat","parseInt","uploadedPercent","Plugin","filePromise","uploadAdapterCreator","id","uid","_filePromiseWrapper","_createFilePromiseWrapper","_adapter","_this4","promise","data","_this5","status","CKEditorError","read","_this6","upload","uploadResponse","isFulfilled","rejecter","wrapper","FileDialogButtonView","locale","_super","call","buttonView","ButtonView","_fileInputView","FileInputView","assertThisInitialized","delegate","setTemplate","tag","attributes","class","children","open","focus","View","_super2","bindTemplate","type","tabindex","accept","multiple","change","element","files","fire","click"],"mappings":"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","file":"js/chunk-090d17a8.aa568526.js","sourcesContent":["/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module upload/filereader\n */\n\n/* globals window */\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Wrapper over the native `FileReader`.\n */\nexport default class FileReader {\n\t/**\n\t * Creates an instance of the FileReader.\n\t */\n\tconstructor() {\n\t\tconst reader = new window.FileReader();\n\n\t\t/**\n\t\t * Instance of native FileReader.\n\t\t *\n\t\t * @private\n\t\t * @member {FileReader} #_reader\n\t\t */\n\t\tthis._reader = reader;\n\n\t\tthis._data = undefined;\n\n\t\t/**\n\t\t * Number of bytes loaded.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #loaded\n\t\t */\n\t\tthis.set( 'loaded', 0 );\n\n\t\treader.onprogress = evt => {\n\t\t\tthis.loaded = evt.loaded;\n\t\t};\n\t}\n\n\t/**\n\t * Returns error that occurred during file reading.\n\t *\n\t * @returns {Error}\n\t */\n\tget error() {\n\t\treturn this._reader.error;\n\t}\n\n\t/**\n\t * Holds the data of an already loaded file. The file must be first loaded\n\t * by using {@link module:upload/filereader~FileReader#read `read()`}.\n\t *\n\t * @type {File|undefined}\n\t */\n\tget data() {\n\t\treturn this._data;\n\t}\n\n\t/**\n\t * Reads the provided file.\n\t *\n\t * @param {File} file Native File object.\n\t * @returns {Promise.} Returns a promise that will be resolved with file's content.\n\t * The promise will be rejected in case of an error or when the reading process is aborted.\n\t */\n\tread( file ) {\n\t\tconst reader = this._reader;\n\t\tthis.total = file.size;\n\n\t\treturn new Promise( ( resolve, reject ) => {\n\t\t\treader.onload = () => {\n\t\t\t\tconst result = reader.result;\n\n\t\t\t\tthis._data = result;\n\n\t\t\t\tresolve( result );\n\t\t\t};\n\n\t\t\treader.onerror = () => {\n\t\t\t\treject( 'error' );\n\t\t\t};\n\n\t\t\treader.onabort = () => {\n\t\t\t\treject( 'aborted' );\n\t\t\t};\n\n\t\t\tthis._reader.readAsDataURL( file );\n\t\t} );\n\t}\n\n\t/**\n\t * Aborts file reader.\n\t */\n\tabort() {\n\t\tthis._reader.abort();\n\t}\n}\n\nmix( FileReader, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module upload/filerepository\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\n\nimport PendingActions from '@ckeditor/ckeditor5-core/src/pendingactions';\nimport CKEditorError, { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport Collection from '@ckeditor/ckeditor5-utils/src/collection';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\nimport FileReader from './filereader.js';\n\nimport uid from '@ckeditor/ckeditor5-utils/src/uid.js';\n\n/**\n * File repository plugin. A central point for managing file upload.\n *\n * To use it, first you need an upload adapter. Upload adapter's job is to handle communication with the server\n * (sending the file and handling server's response). You can use one of the existing plugins introducing upload adapters\n * (e.g. {@link module:easy-image/cloudservicesuploadadapter~CloudServicesUploadAdapter} or\n * {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter}) or write your own one – see\n * the {@glink framework/guides/deep-dive/upload-adapter Custom image upload adapter deep dive guide}.\n *\n * Then, you can use {@link module:upload/filerepository~FileRepository#createLoader `createLoader()`} and the returned\n * {@link module:upload/filerepository~FileLoader} instance to load and upload files.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class FileRepository extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'FileRepository';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ PendingActions ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\t/**\n\t\t * Collection of loaders associated with this repository.\n\t\t *\n\t\t * @member {module:utils/collection~Collection} #loaders\n\t\t */\n\t\tthis.loaders = new Collection();\n\n\t\t// Keeps upload in a sync with pending actions.\n\t\tthis.loaders.on( 'add', () => this._updatePendingAction() );\n\t\tthis.loaders.on( 'remove', () => this._updatePendingAction() );\n\n\t\t/**\n\t\t * Loaders mappings used to retrieve loaders references.\n\t\t *\n\t\t * @private\n\t\t * @member {Map} #_loadersMap\n\t\t */\n\t\tthis._loadersMap = new Map();\n\n\t\t/**\n\t\t * Reference to a pending action registered in a {@link module:core/pendingactions~PendingActions} plugin\n\t\t * while upload is in progress. When there is no upload then value is `null`.\n\t\t *\n\t\t * @private\n\t\t * @member {Object} #_pendingAction\n\t\t */\n\t\tthis._pendingAction = null;\n\n\t\t/**\n\t\t * A factory function which should be defined before using `FileRepository`.\n\t\t *\n\t\t * It should return a new instance of {@link module:upload/filerepository~UploadAdapter} that will be used to upload files.\n\t\t * {@link module:upload/filerepository~FileLoader} instance associated with the adapter\n\t\t * will be passed to that function.\n\t\t *\n\t\t * For more information and example see {@link module:upload/filerepository~UploadAdapter}.\n\t\t *\n\t\t * @member {Function} #createUploadAdapter\n\t\t */\n\n\t\t/**\n\t\t * Number of bytes uploaded.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #uploaded\n\t\t */\n\t\tthis.set( 'uploaded', 0 );\n\n\t\t/**\n\t\t * Number of total bytes to upload.\n\t\t *\n\t\t * It might be different than the file size because of headers and additional data.\n\t\t * It contains `null` if value is not available yet, so it's better to use {@link #uploadedPercent} to monitor\n\t\t * the progress.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number|null} #uploadTotal\n\t\t */\n\t\tthis.set( 'uploadTotal', null );\n\n\t\t/**\n\t\t * Upload progress in percents.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #uploadedPercent\n\t\t */\n\t\tthis.bind( 'uploadedPercent' ).to( this, 'uploaded', this, 'uploadTotal', ( uploaded, total ) => {\n\t\t\treturn total ? ( uploaded / total * 100 ) : 0;\n\t\t} );\n\t}\n\n\t/**\n\t * Returns the loader associated with specified file or promise.\n\t *\n\t * To get loader by id use `fileRepository.loaders.get( id )`.\n\t *\n\t * @param {File|Promise.} fileOrPromise Native file or promise handle.\n\t * @returns {module:upload/filerepository~FileLoader|null}\n\t */\n\tgetLoader( fileOrPromise ) {\n\t\treturn this._loadersMap.get( fileOrPromise ) || null;\n\t}\n\n\t/**\n\t * Creates a loader instance for the given file.\n\t *\n\t * Requires {@link #createUploadAdapter} factory to be defined.\n\t *\n\t * @param {File|Promise.} fileOrPromise Native File object or native Promise object which resolves to a File.\n\t * @returns {module:upload/filerepository~FileLoader|null}\n\t */\n\tcreateLoader( fileOrPromise ) {\n\t\tif ( !this.createUploadAdapter ) {\n\t\t\t/**\n\t\t\t * You need to enable an upload adapter in order to be able to upload files.\n\t\t\t *\n\t\t\t * This warning shows up when {@link module:upload/filerepository~FileRepository} is being used\n\t\t\t * without {@link #createUploadAdapter defining an upload adapter}.\n\t\t\t *\n\t\t\t * **If you see this warning when using one of the {@glink builds/index CKEditor 5 Builds}**\n\t\t\t * it means that you did not configure any of the upload adapters available by default in those builds.\n\t\t\t *\n\t\t\t * See the {@glink features/images/image-upload/image-upload comprehensive \"Image upload overview\"} to learn which upload\n\t\t\t * adapters are available in the builds and how to configure them.\n\t\t\t *\n\t\t\t * **If you see this warning when using a custom build** there is a chance that you enabled\n\t\t\t * a feature like {@link module:image/imageupload~ImageUpload},\n\t\t\t * or {@link module:image/imageupload/imageuploadui~ImageUploadUI} but you did not enable any upload adapter.\n\t\t\t * You can choose one of the existing upload adapters listed in the\n\t\t\t * {@glink features/images/image-upload/image-upload \"Image upload overview\"}.\n\t\t\t *\n\t\t\t * You can also implement your {@glink framework/guides/deep-dive/upload-adapter own image upload adapter}.\n\t\t\t *\n\t\t\t * @error filerepository-no-upload-adapter\n\t\t\t */\n\t\t\tlogWarning( 'filerepository-no-upload-adapter' );\n\n\t\t\treturn null;\n\t\t}\n\n\t\tconst loader = new FileLoader( Promise.resolve( fileOrPromise ), this.createUploadAdapter );\n\n\t\tthis.loaders.add( loader );\n\t\tthis._loadersMap.set( fileOrPromise, loader );\n\n\t\t// Store also file => loader mapping so loader can be retrieved by file instance returned upon Promise resolution.\n\t\tif ( fileOrPromise instanceof Promise ) {\n\t\t\tloader.file\n\t\t\t\t.then( file => {\n\t\t\t\t\tthis._loadersMap.set( file, loader );\n\t\t\t\t} )\n\t\t\t\t// Every then() must have a catch().\n\t\t\t\t// File loader state (and rejections) are handled in read() and upload().\n\t\t\t\t// Also, see the \"does not swallow the file promise rejection\" test.\n\t\t\t\t.catch( () => {} );\n\t\t}\n\n\t\tloader.on( 'change:uploaded', () => {\n\t\t\tlet aggregatedUploaded = 0;\n\n\t\t\tfor ( const loader of this.loaders ) {\n\t\t\t\taggregatedUploaded += loader.uploaded;\n\t\t\t}\n\n\t\t\tthis.uploaded = aggregatedUploaded;\n\t\t} );\n\n\t\tloader.on( 'change:uploadTotal', () => {\n\t\t\tlet aggregatedTotal = 0;\n\n\t\t\tfor ( const loader of this.loaders ) {\n\t\t\t\tif ( loader.uploadTotal ) {\n\t\t\t\t\taggregatedTotal += loader.uploadTotal;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.uploadTotal = aggregatedTotal;\n\t\t} );\n\n\t\treturn loader;\n\t}\n\n\t/**\n\t * Destroys the given loader.\n\t *\n\t * @param {File|Promise|module:upload/filerepository~FileLoader} fileOrPromiseOrLoader File or Promise associated\n\t * with that loader or loader itself.\n\t */\n\tdestroyLoader( fileOrPromiseOrLoader ) {\n\t\tconst loader = fileOrPromiseOrLoader instanceof FileLoader ? fileOrPromiseOrLoader : this.getLoader( fileOrPromiseOrLoader );\n\n\t\tloader._destroy();\n\n\t\tthis.loaders.remove( loader );\n\n\t\tthis._loadersMap.forEach( ( value, key ) => {\n\t\t\tif ( value === loader ) {\n\t\t\t\tthis._loadersMap.delete( key );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Registers or deregisters pending action bound with upload progress.\n\t *\n\t * @private\n\t */\n\t_updatePendingAction() {\n\t\tconst pendingActions = this.editor.plugins.get( PendingActions );\n\n\t\tif ( this.loaders.length ) {\n\t\t\tif ( !this._pendingAction ) {\n\t\t\t\tconst t = this.editor.t;\n\t\t\t\tconst getMessage = value => `${ t( 'Upload in progress' ) } ${ parseInt( value ) }%.`;\n\n\t\t\t\tthis._pendingAction = pendingActions.add( getMessage( this.uploadedPercent ) );\n\t\t\t\tthis._pendingAction.bind( 'message' ).to( this, 'uploadedPercent', getMessage );\n\t\t\t}\n\t\t} else {\n\t\t\tpendingActions.remove( this._pendingAction );\n\t\t\tthis._pendingAction = null;\n\t\t}\n\t}\n}\n\nmix( FileRepository, ObservableMixin );\n\n/**\n * File loader class.\n *\n * It is used to control the process of reading the file and uploading it using the specified upload adapter.\n */\nclass FileLoader {\n\t/**\n\t * Creates a new instance of `FileLoader`.\n\t *\n\t * @param {Promise.} filePromise A promise which resolves to a file instance.\n\t * @param {Function} uploadAdapterCreator The function which returns {@link module:upload/filerepository~UploadAdapter} instance.\n\t */\n\tconstructor( filePromise, uploadAdapterCreator ) {\n\t\t/**\n\t\t * Unique id of FileLoader instance.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number}\n\t\t */\n\t\tthis.id = uid();\n\n\t\t/**\n\t\t * Additional wrapper over the initial file promise passed to this loader.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:upload/filerepository~FilePromiseWrapper}\n\t\t */\n\t\tthis._filePromiseWrapper = this._createFilePromiseWrapper( filePromise );\n\n\t\t/**\n\t\t * Adapter instance associated with this file loader.\n\t\t *\n\t\t * @private\n\t\t * @member {module:upload/filerepository~UploadAdapter}\n\t\t */\n\t\tthis._adapter = uploadAdapterCreator( this );\n\n\t\t/**\n\t\t * FileReader used by FileLoader.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:upload/filereader~FileReader}\n\t\t */\n\t\tthis._reader = new FileReader();\n\n\t\t/**\n\t\t * Current status of FileLoader. It can be one of the following:\n\t\t *\n\t\t * * 'idle',\n\t\t * * 'reading',\n\t\t * * 'uploading',\n\t\t * * 'aborted',\n\t\t * * 'error'.\n\t\t *\n\t\t * When reading status can change in a following way:\n\t\t *\n\t\t * `idle` -> `reading` -> `idle`\n\t\t * `idle` -> `reading -> `aborted`\n\t\t * `idle` -> `reading -> `error`\n\t\t *\n\t\t * When uploading status can change in a following way:\n\t\t *\n\t\t * `idle` -> `uploading` -> `idle`\n\t\t * `idle` -> `uploading` -> `aborted`\n\t\t * `idle` -> `uploading` -> `error`\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {String} #status\n\t\t */\n\t\tthis.set( 'status', 'idle' );\n\n\t\t/**\n\t\t * Number of bytes uploaded.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #uploaded\n\t\t */\n\t\tthis.set( 'uploaded', 0 );\n\n\t\t/**\n\t\t * Number of total bytes to upload.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number|null} #uploadTotal\n\t\t */\n\t\tthis.set( 'uploadTotal', null );\n\n\t\t/**\n\t\t * Upload progress in percents.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number} #uploadedPercent\n\t\t */\n\t\tthis.bind( 'uploadedPercent' ).to( this, 'uploaded', this, 'uploadTotal', ( uploaded, total ) => {\n\t\t\treturn total ? ( uploaded / total * 100 ) : 0;\n\t\t} );\n\n\t\t/**\n\t\t * Response of the upload.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Object|null} #uploadResponse\n\t\t */\n\t\tthis.set( 'uploadResponse', null );\n\t}\n\n\t/**\n\t * A `Promise` which resolves to a `File` instance associated with this file loader.\n\t *\n\t * @type {Promise.}\n\t */\n\tget file() {\n\t\tif ( !this._filePromiseWrapper ) {\n\t\t\t// Loader was destroyed, return promise which resolves to null.\n\t\t\treturn Promise.resolve( null );\n\t\t} else {\n\t\t\t// The `this._filePromiseWrapper.promise` is chained and not simply returned to handle a case when:\n\t\t\t//\n\t\t\t//\t\t* The `loader.file.then( ... )` is called by external code (returned promise is pending).\n\t\t\t//\t\t* Then `loader._destroy()` is called (call is synchronous) which destroys the `loader`.\n\t\t\t//\t\t* Promise returned by the first `loader.file.then( ... )` call is resolved.\n\t\t\t//\n\t\t\t// Returning `this._filePromiseWrapper.promise` will still resolve to a `File` instance so there\n\t\t\t// is an additional check needed in the chain to see if `loader` was destroyed in the meantime.\n\t\t\treturn this._filePromiseWrapper.promise.then( file => this._filePromiseWrapper ? file : null );\n\t\t}\n\t}\n\n\t/**\n\t * Returns the file data. To read its data, you need for first load the file\n\t * by using the {@link module:upload/filerepository~FileLoader#read `read()`} method.\n\t *\n\t * @type {File|undefined}\n\t */\n\tget data() {\n\t\treturn this._reader.data;\n\t}\n\n\t/**\n\t * Reads file using {@link module:upload/filereader~FileReader}.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `filerepository-read-wrong-status` when status\n\t * is different than `idle`.\n\t *\n\t * Example usage:\n\t *\n\t *\tfileLoader.read()\n\t *\t\t.then( data => { ... } )\n\t *\t\t.catch( err => {\n\t *\t\t\tif ( err === 'aborted' ) {\n\t *\t\t\t\tconsole.log( 'Reading aborted.' );\n\t *\t\t\t} else {\n\t *\t\t\t\tconsole.log( 'Reading error.', err );\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * @returns {Promise.} Returns promise that will be resolved with read data. Promise will be rejected if error\n\t * occurs or if read process is aborted.\n\t */\n\tread() {\n\t\tif ( this.status != 'idle' ) {\n\t\t\t/**\n\t\t\t * You cannot call read if the status is different than idle.\n\t\t\t *\n\t\t\t * @error filerepository-read-wrong-status\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'filerepository-read-wrong-status', this );\n\t\t}\n\n\t\tthis.status = 'reading';\n\n\t\treturn this.file\n\t\t\t.then( file => this._reader.read( file ) )\n\t\t\t.then( data => {\n\t\t\t\t// Edge case: reader was aborted after file was read - double check for proper status.\n\t\t\t\t// It can happen when image was deleted during its upload.\n\t\t\t\tif ( this.status !== 'reading' ) {\n\t\t\t\t\tthrow this.status;\n\t\t\t\t}\n\n\t\t\t\tthis.status = 'idle';\n\n\t\t\t\treturn data;\n\t\t\t} )\n\t\t\t.catch( err => {\n\t\t\t\tif ( err === 'aborted' ) {\n\t\t\t\t\tthis.status = 'aborted';\n\t\t\t\t\tthrow 'aborted';\n\t\t\t\t}\n\n\t\t\t\tthis.status = 'error';\n\t\t\t\tthrow this._reader.error ? this._reader.error : err;\n\t\t\t} );\n\t}\n\n\t/**\n\t * Reads file using the provided {@link module:upload/filerepository~UploadAdapter}.\n\t *\n\t * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `filerepository-upload-wrong-status` when status\n\t * is different than `idle`.\n\t * Example usage:\n\t *\n\t *\tfileLoader.upload()\n\t *\t\t.then( data => { ... } )\n\t *\t\t.catch( e => {\n\t *\t\t\tif ( e === 'aborted' ) {\n\t *\t\t\t\tconsole.log( 'Uploading aborted.' );\n\t *\t\t\t} else {\n\t *\t\t\t\tconsole.log( 'Uploading error.', e );\n\t *\t\t\t}\n\t *\t\t} );\n\t *\n\t * @returns {Promise.} Returns promise that will be resolved with response data. Promise will be rejected if error\n\t * occurs or if read process is aborted.\n\t */\n\tupload() {\n\t\tif ( this.status != 'idle' ) {\n\t\t\t/**\n\t\t\t * You cannot call upload if the status is different than idle.\n\t\t\t *\n\t\t\t * @error filerepository-upload-wrong-status\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'filerepository-upload-wrong-status', this );\n\t\t}\n\n\t\tthis.status = 'uploading';\n\n\t\treturn this.file\n\t\t\t.then( () => this._adapter.upload() )\n\t\t\t.then( data => {\n\t\t\t\tthis.uploadResponse = data;\n\t\t\t\tthis.status = 'idle';\n\n\t\t\t\treturn data;\n\t\t\t} )\n\t\t\t.catch( err => {\n\t\t\t\tif ( this.status === 'aborted' ) {\n\t\t\t\t\tthrow 'aborted';\n\t\t\t\t}\n\n\t\t\t\tthis.status = 'error';\n\t\t\t\tthrow err;\n\t\t\t} );\n\t}\n\n\t/**\n\t * Aborts loading process.\n\t */\n\tabort() {\n\t\tconst status = this.status;\n\t\tthis.status = 'aborted';\n\n\t\tif ( !this._filePromiseWrapper.isFulfilled ) {\n\t\t\t// Edge case: file loader is aborted before read() is called\n\t\t\t// so it might happen that no one handled the rejection of this promise.\n\t\t\t// See https://github.com/ckeditor/ckeditor5-upload/pull/100\n\t\t\tthis._filePromiseWrapper.promise.catch( () => {} );\n\n\t\t\tthis._filePromiseWrapper.rejecter( 'aborted' );\n\t\t} else if ( status == 'reading' ) {\n\t\t\tthis._reader.abort();\n\t\t} else if ( status == 'uploading' && this._adapter.abort ) {\n\t\t\tthis._adapter.abort();\n\t\t}\n\n\t\tthis._destroy();\n\t}\n\n\t/**\n\t * Performs cleanup.\n\t *\n\t * @private\n\t */\n\t_destroy() {\n\t\tthis._filePromiseWrapper = undefined;\n\t\tthis._reader = undefined;\n\t\tthis._adapter = undefined;\n\t\tthis.uploadResponse = undefined;\n\t}\n\n\t/**\n\t * Wraps a given file promise into another promise giving additional\n\t * control (resolving, rejecting, checking if fulfilled) over it.\n\t *\n\t * @private\n\t * @param filePromise The initial file promise to be wrapped.\n\t * @returns {module:upload/filerepository~FilePromiseWrapper}\n\t */\n\t_createFilePromiseWrapper( filePromise ) {\n\t\tconst wrapper = {};\n\n\t\twrapper.promise = new Promise( ( resolve, reject ) => {\n\t\t\twrapper.rejecter = reject;\n\t\t\twrapper.isFulfilled = false;\n\n\t\t\tfilePromise\n\t\t\t\t.then( file => {\n\t\t\t\t\twrapper.isFulfilled = true;\n\t\t\t\t\tresolve( file );\n\t\t\t\t} )\n\t\t\t\t.catch( err => {\n\t\t\t\t\twrapper.isFulfilled = true;\n\t\t\t\t\treject( err );\n\t\t\t\t} );\n\t\t} );\n\n\t\treturn wrapper;\n\t}\n}\n\nmix( FileLoader, ObservableMixin );\n\n/**\n * Upload adapter interface used by the {@link module:upload/filerepository~FileRepository file repository}\n * to handle file upload. An upload adapter is a bridge between the editor and server that handles file uploads.\n * It should contain a logic necessary to initiate an upload process and monitor its progress.\n *\n * Learn how to develop your own upload adapter for CKEditor 5 in the\n * {@glink framework/guides/deep-dive/upload-adapter \"Custom upload adapter\" guide}.\n *\n * @interface UploadAdapter\n */\n\n/**\n * Executes the upload process.\n * This method should return a promise that will resolve when data will be uploaded to server. Promise should be\n * resolved with an object containing information about uploaded file:\n *\n *\t\t{\n *\t\t\tdefault: 'http://server/default-size.image.png'\n *\t\t}\n *\n * Additionally, other image sizes can be provided:\n *\n *\t\t{\n *\t\t\tdefault: 'http://server/default-size.image.png',\n *\t\t\t'160': 'http://server/size-160.image.png',\n *\t\t\t'500': 'http://server/size-500.image.png',\n *\t\t\t'1000': 'http://server/size-1000.image.png',\n *\t\t\t'1052': 'http://server/default-size.image.png'\n *\t\t}\n *\n * You can also pass additional properties from the server. In this case you need to wrap URLs\n * in the `urls` object and pass additional properties along the `urls` property.\n *\n * \t\t{\n * \t\t\tmyCustomProperty: 'foo',\n * \t\t\turls: {\n *\t\t\t\tdefault: 'http://server/default-size.image.png',\n *\t\t\t\t'160': 'http://server/size-160.image.png',\n *\t\t\t\t'500': 'http://server/size-500.image.png',\n *\t\t\t\t'1000': 'http://server/size-1000.image.png',\n *\t\t\t\t'1052': 'http://server/default-size.image.png'\n *\t\t\t}\n *\t\t}\n *\n * NOTE: When returning multiple images, the widest returned one should equal the default one. It is essential to\n * correctly set `width` attribute of the image. See this discussion:\n * https://github.com/ckeditor/ckeditor5-easy-image/issues/4 for more information.\n *\n * Take a look at {@link module:upload/filerepository~UploadAdapter example Adapter implementation} and\n * {@link module:upload/filerepository~FileRepository#createUploadAdapter createUploadAdapter method}.\n *\n * @method module:upload/filerepository~UploadAdapter#upload\n * @returns {Promise.} Promise that should be resolved when data is uploaded.\n */\n\n/**\n * Aborts the upload process.\n * After aborting it should reject promise returned from {@link #upload upload()}.\n *\n * Take a look at {@link module:upload/filerepository~UploadAdapter example Adapter implementation} and\n * {@link module:upload/filerepository~FileRepository#createUploadAdapter createUploadAdapter method}.\n *\n * @method module:upload/filerepository~UploadAdapter#abort\n */\n\n/**\n * Object returned by {@link module:upload/filerepository~FileLoader#_createFilePromiseWrapper} method\n * to add more control over the initial file promise passed to {@link module:upload/filerepository~FileLoader}.\n *\n * @protected\n * @typedef {Object} module:upload/filerepository~FilePromiseWrapper\n * @property {Promise.} promise Wrapper promise which can be chained for further processing.\n * @property {Function} rejecter Rejects the promise when called.\n * @property {Boolean} isFulfilled Whether original promise is already fulfilled.\n */\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module upload/ui/filedialogbuttonview\n */\n\nimport ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';\nimport View from '@ckeditor/ckeditor5-ui/src/view';\n\n/**\n * The file dialog button view.\n *\n * This component provides a button that opens the native file selection dialog.\n * It can be used to implement the UI of a file upload feature.\n *\n *\t\tconst view = new FileDialogButtonView( locale );\n *\n *\t\tview.set( {\n *\t\t\tacceptedType: 'image/*',\n *\t\t\tallowMultipleFiles: true\n *\t\t} );\n *\n *\t\tview.buttonView.set( {\n *\t\t\tlabel: t( 'Insert image' ),\n *\t\t\ticon: imageIcon,\n *\t\t\ttooltip: true\n *\t\t} );\n *\n *\t\tview.on( 'done', ( evt, files ) => {\n *\t\t\tfor ( const file of Array.from( files ) ) {\n *\t\t\t\tconsole.log( 'Selected file', file );\n *\t\t\t}\n *\t\t} );\n *\n * @extends module:ui/view~View\n */\nexport default class FileDialogButtonView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * The button view of the component.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n\t\tthis.buttonView = new ButtonView( locale );\n\n\t\t/**\n\t\t * A hidden `` view used to execute file dialog.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:upload/ui/filedialogbuttonview~FileInputView}\n\t\t */\n\t\tthis._fileInputView = new FileInputView( locale );\n\n\t\t/**\n\t\t * Accepted file types. Can be provided in form of file extensions, media type or one of:\n\t\t * * `audio/*`,\n\t\t * * `video/*`,\n\t\t * * `image/*`.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #acceptedType\n\t\t */\n\t\tthis._fileInputView.bind( 'acceptedType' ).to( this );\n\n\t\t/**\n\t\t * Indicates if multiple files can be selected. Defaults to `true`.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #allowMultipleFiles\n\t\t */\n\t\tthis._fileInputView.bind( 'allowMultipleFiles' ).to( this );\n\n\t\t/**\n\t\t * Fired when file dialog is closed with file selected.\n\t\t *\n\t\t *\t\tview.on( 'done', ( evt, files ) => {\n\t\t *\t\t\tfor ( const file of files ) {\n\t\t *\t\t\t\tconsole.log( 'Selected file', file );\n\t\t *\t\t\t}\n\t\t *\t\t}\n\t\t *\n\t\t * @event done\n\t\t * @param {Array.} files Array of selected files.\n\t\t */\n\t\tthis._fileInputView.delegate( 'done' ).to( this );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'span',\n\t\t\tattributes: {\n\t\t\t\tclass: 'ck-file-dialog-button'\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\tthis.buttonView,\n\t\t\t\tthis._fileInputView\n\t\t\t]\n\t\t} );\n\n\t\tthis.buttonView.on( 'execute', () => {\n\t\t\tthis._fileInputView.open();\n\t\t} );\n\t}\n\n\t/**\n\t * Focuses the {@link #buttonView}.\n\t */\n\tfocus() {\n\t\tthis.buttonView.focus();\n\t}\n}\n\n/**\n * The hidden file input view class.\n *\n * @private\n * @extends module:ui/view~View\n */\nclass FileInputView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\t/**\n\t\t * Accepted file types. Can be provided in form of file extensions, media type or one of:\n\t\t * * `audio/*`,\n\t\t * * `video/*`,\n\t\t * * `image/*`.\n\t\t *\n\t\t * @observable\n\t\t * @member {String} #acceptedType\n\t\t */\n\t\tthis.set( 'acceptedType' );\n\n\t\t/**\n\t\t * Indicates if multiple files can be selected. Defaults to `false`.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} #allowMultipleFiles\n\t\t */\n\t\tthis.set( 'allowMultipleFiles', false );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'input',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck-hidden'\n\t\t\t\t],\n\t\t\t\ttype: 'file',\n\t\t\t\ttabindex: '-1',\n\t\t\t\taccept: bind.to( 'acceptedType' ),\n\t\t\t\tmultiple: bind.to( 'allowMultipleFiles' )\n\t\t\t},\n\n\t\t\ton: {\n\t\t\t\t// Removing from code coverage since we cannot programmatically set input element files.\n\t\t\t\tchange: bind.to( /* istanbul ignore next */ () => {\n\t\t\t\t\tif ( this.element && this.element.files && this.element.files.length ) {\n\t\t\t\t\t\tthis.fire( 'done', this.element.files );\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.element.value = '';\n\t\t\t\t} )\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Opens file dialog.\n\t */\n\topen() {\n\t\tthis.element.click();\n\t}\n}\n"],"sourceRoot":""}