(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Uppy = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
        module.exports = after

        function after(count, callback, err_cb) {
            var bail = false
            err_cb = err_cb || noop
            proxy.count = count

            return (count === 0) ? callback() : proxy

            function proxy(err, result) {
                if (proxy.count <= 0) {
                    throw new Error('after called too many times')
                }
                --proxy.count

                // after first error, rest are passed to err_cb
                if (err) {
                    bail = true
                    callback(err)
                    // future error callbacks will go to error handler
                    callback = err_cb
                } else if (proxy.count === 0 && !bail) {
                    callback(null, result)
                }
            }
        }

        function noop() {}

    },{}],2:[function(require,module,exports){

        /**
         * Expose `Backoff`.
         */

        module.exports = Backoff;

        /**
         * Initialize backoff timer with `opts`.
         *
         * - `min` initial timeout in milliseconds [100]
         * - `max` max timeout [10000]
         * - `jitter` [0]
         * - `factor` [2]
         *
         * @param {Object} opts
         * @api public
         */

        function Backoff(opts) {
            opts = opts || {};
            this.ms = opts.min || 100;
            this.max = opts.max || 10000;
            this.factor = opts.factor || 2;
            this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
            this.attempts = 0;
        }

        /**
         * Return the backoff duration.
         *
         * @return {Number}
         * @api public
         */

        Backoff.prototype.duration = function(){
            var ms = this.ms * Math.pow(this.factor, this.attempts++);
            if (this.jitter) {
                var rand =  Math.random();
                var deviation = Math.floor(rand * this.jitter * ms);
                ms = (Math.floor(rand * 10) & 1) == 0  ? ms - deviation : ms + deviation;
            }
            return Math.min(ms, this.max) | 0;
        };

        /**
         * Reset the number of attempts.
         *
         * @api public
         */

        Backoff.prototype.reset = function(){
            this.attempts = 0;
        };

        /**
         * Set the minimum duration
         *
         * @api public
         */

        Backoff.prototype.setMin = function(min){
            this.ms = min;
        };

        /**
         * Set the maximum duration
         *
         * @api public
         */

        Backoff.prototype.setMax = function(max){
            this.max = max;
        };

        /**
         * Set the jitter
         *
         * @api public
         */

        Backoff.prototype.setJitter = function(jitter){
            this.jitter = jitter;
        };


    },{}],3:[function(require,module,exports){
        /*
 * base64-arraybuffer
 * https://github.com/niklasvh/base64-arraybuffer
 *
 * Copyright (c) 2012 Niklas von Hertzen
 * Licensed under the MIT license.
 */
        (function(){
            "use strict";

            var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

            // Use a lookup table to find the index.
            var lookup = new Uint8Array(256);
            for (var i = 0; i < chars.length; i++) {
                lookup[chars.charCodeAt(i)] = i;
            }

            exports.encode = function(arraybuffer) {
                var bytes = new Uint8Array(arraybuffer),
                    i, len = bytes.length, base64 = "";

                for (i = 0; i < len; i+=3) {
                    base64 += chars[bytes[i] >> 2];
                    base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
                    base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
                    base64 += chars[bytes[i + 2] & 63];
                }

                if ((len % 3) === 2) {
                    base64 = base64.substring(0, base64.length - 1) + "=";
                } else if (len % 3 === 1) {
                    base64 = base64.substring(0, base64.length - 2) + "==";
                }

                return base64;
            };

            exports.decode =  function(base64) {
                var bufferLength = base64.length * 0.75,
                    len = base64.length, i, p = 0,
                    encoded1, encoded2, encoded3, encoded4;

                if (base64[base64.length - 1] === "=") {
                    bufferLength--;
                    if (base64[base64.length - 2] === "=") {
                        bufferLength--;
                    }
                }

                var arraybuffer = new ArrayBuffer(bufferLength),
                    bytes = new Uint8Array(arraybuffer);

                for (i = 0; i < len; i+=4) {
                    encoded1 = lookup[base64.charCodeAt(i)];
                    encoded2 = lookup[base64.charCodeAt(i+1)];
                    encoded3 = lookup[base64.charCodeAt(i+2)];
                    encoded4 = lookup[base64.charCodeAt(i+3)];

                    bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
                    bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
                    bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
                }

                return arraybuffer;
            };
        })();

    },{}],4:[function(require,module,exports){
        (function (global){
            /**
             * Create a blob builder even when vendor prefixes exist
             */

            var BlobBuilder = global.BlobBuilder
                || global.WebKitBlobBuilder
                || global.MSBlobBuilder
                || global.MozBlobBuilder;

            /**
             * Check if Blob constructor is supported
             */

            var blobSupported = (function() {
                try {
                    var a = new Blob(['hi']);
                    return a.size === 2;
                } catch(e) {
                    return false;
                }
            })();

            /**
             * Check if Blob constructor supports ArrayBufferViews
             * Fails in Safari 6, so we need to map to ArrayBuffers there.
             */

            var blobSupportsArrayBufferView = blobSupported && (function() {
                try {
                    var b = new Blob([new Uint8Array([1,2])]);
                    return b.size === 2;
                } catch(e) {
                    return false;
                }
            })();

            /**
             * Check if BlobBuilder is supported
             */

            var blobBuilderSupported = BlobBuilder
                && BlobBuilder.prototype.append
                && BlobBuilder.prototype.getBlob;

            /**
             * Helper function that maps ArrayBufferViews to ArrayBuffers
             * Used by BlobBuilder constructor and old browsers that didn't
             * support it in the Blob constructor.
             */

            function mapArrayBufferViews(ary) {
                for (var i = 0; i < ary.length; i++) {
                    var chunk = ary[i];
                    if (chunk.buffer instanceof ArrayBuffer) {
                        var buf = chunk.buffer;

                        // if this is a subarray, make a copy so we only
                        // include the subarray region from the underlying buffer
                        if (chunk.byteLength !== buf.byteLength) {
                            var copy = new Uint8Array(chunk.byteLength);
                            copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
                            buf = copy.buffer;
                        }

                        ary[i] = buf;
                    }
                }
            }

            function BlobBuilderConstructor(ary, options) {
                options = options || {};

                var bb = new BlobBuilder();
                mapArrayBufferViews(ary);

                for (var i = 0; i < ary.length; i++) {
                    bb.append(ary[i]);
                }

                return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
            };

            function BlobConstructor(ary, options) {
                mapArrayBufferViews(ary);
                return new Blob(ary, options || {});
            };

            module.exports = (function() {
                if (blobSupported) {
                    return blobSupportsArrayBufferView ? global.Blob : BlobConstructor;
                } else if (blobBuilderSupported) {
                    return BlobBuilderConstructor;
                } else {
                    return undefined;
                }
            })();

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{}],5:[function(require,module,exports){

    },{}],6:[function(require,module,exports){
// shim for using process in browser
        var process = module.exports = {};

// cached from whatever global is present so that test runners that stub it
// don't break things.  But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals.  It's inside a
// function because try/catches deoptimize in certain engines.

        var cachedSetTimeout;
        var cachedClearTimeout;

        function defaultSetTimout() {
            throw new Error('setTimeout has not been defined');
        }
        function defaultClearTimeout () {
            throw new Error('clearTimeout has not been defined');
        }
        (function () {
            try {
                if (typeof setTimeout === 'function') {
                    cachedSetTimeout = setTimeout;
                } else {
                    cachedSetTimeout = defaultSetTimout;
                }
            } catch (e) {
                cachedSetTimeout = defaultSetTimout;
            }
            try {
                if (typeof clearTimeout === 'function') {
                    cachedClearTimeout = clearTimeout;
                } else {
                    cachedClearTimeout = defaultClearTimeout;
                }
            } catch (e) {
                cachedClearTimeout = defaultClearTimeout;
            }
        } ())
        function runTimeout(fun) {
            if (cachedSetTimeout === setTimeout) {
                //normal enviroments in sane situations
                return setTimeout(fun, 0);
            }
            // if setTimeout wasn't available but was latter defined
            if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
                cachedSetTimeout = setTimeout;
                return setTimeout(fun, 0);
            }
            try {
                // when when somebody has screwed with setTimeout but no I.E. maddness
                return cachedSetTimeout(fun, 0);
            } catch(e){
                try {
                    // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
                    return cachedSetTimeout.call(null, fun, 0);
                } catch(e){
                    // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
                    return cachedSetTimeout.call(this, fun, 0);
                }
            }


        }
        function runClearTimeout(marker) {
            if (cachedClearTimeout === clearTimeout) {
                //normal enviroments in sane situations
                return clearTimeout(marker);
            }
            // if clearTimeout wasn't available but was latter defined
            if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
                cachedClearTimeout = clearTimeout;
                return clearTimeout(marker);
            }
            try {
                // when when somebody has screwed with setTimeout but no I.E. maddness
                return cachedClearTimeout(marker);
            } catch (e){
                try {
                    // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
                    return cachedClearTimeout.call(null, marker);
                } catch (e){
                    // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
                    // Some versions of I.E. have different rules for clearTimeout vs setTimeout
                    return cachedClearTimeout.call(this, marker);
                }
            }



        }
        var queue = [];
        var draining = false;
        var currentQueue;
        var queueIndex = -1;

        function cleanUpNextTick() {
            if (!draining || !currentQueue) {
                return;
            }
            draining = false;
            if (currentQueue.length) {
                queue = currentQueue.concat(queue);
            } else {
                queueIndex = -1;
            }
            if (queue.length) {
                drainQueue();
            }
        }

        function drainQueue() {
            if (draining) {
                return;
            }
            var timeout = runTimeout(cleanUpNextTick);
            draining = true;

            var len = queue.length;
            while(len) {
                currentQueue = queue;
                queue = [];
                while (++queueIndex < len) {
                    if (currentQueue) {
                        currentQueue[queueIndex].run();
                    }
                }
                queueIndex = -1;
                len = queue.length;
            }
            currentQueue = null;
            draining = false;
            runClearTimeout(timeout);
        }

        process.nextTick = function (fun) {
            var args = new Array(arguments.length - 1);
            if (arguments.length > 1) {
                for (var i = 1; i < arguments.length; i++) {
                    args[i - 1] = arguments[i];
                }
            }
            queue.push(new Item(fun, args));
            if (queue.length === 1 && !draining) {
                runTimeout(drainQueue);
            }
        };

// v8 likes predictible objects
        function Item(fun, array) {
            this.fun = fun;
            this.array = array;
        }
        Item.prototype.run = function () {
            this.fun.apply(null, this.array);
        };
        process.title = 'browser';
        process.browser = true;
        process.env = {};
        process.argv = [];
        process.version = ''; // empty string to avoid regexp issues
        process.versions = {};

        function noop() {}

        process.on = noop;
        process.addListener = noop;
        process.once = noop;
        process.off = noop;
        process.removeListener = noop;
        process.removeAllListeners = noop;
        process.emit = noop;
        process.prependListener = noop;
        process.prependOnceListener = noop;

        process.listeners = function (name) { return [] }

        process.binding = function (name) {
            throw new Error('process.binding is not supported');
        };

        process.cwd = function () { return '/' };
        process.chdir = function (dir) {
            throw new Error('process.chdir is not supported');
        };
        process.umask = function() { return 0; };

    },{}],7:[function(require,module,exports){
        /*!
  Copyright (c) 2016 Jed Watson.
  Licensed under the MIT License (MIT), see
  http://jedwatson.github.io/classnames
*/
        /* global define */

        (function () {
            'use strict';

            var hasOwn = {}.hasOwnProperty;

            function classNames () {
                var classes = [];

                for (var i = 0; i < arguments.length; i++) {
                    var arg = arguments[i];
                    if (!arg) continue;

                    var argType = typeof arg;

                    if (argType === 'string' || argType === 'number') {
                        classes.push(arg);
                    } else if (Array.isArray(arg)) {
                        classes.push(classNames.apply(null, arg));
                    } else if (argType === 'object') {
                        for (var key in arg) {
                            if (hasOwn.call(arg, key) && arg[key]) {
                                classes.push(key);
                            }
                        }
                    }
                }

                return classes.join(' ');
            }

            if (typeof module !== 'undefined' && module.exports) {
                module.exports = classNames;
            } else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
                // register as 'classnames', consistent with npm package name
                define('classnames', [], function () {
                    return classNames;
                });
            } else {
                window.classNames = classNames;
            }
        }());

    },{}],8:[function(require,module,exports){
        /**
         * Slice reference.
         */

        var slice = [].slice;

        /**
         * Bind `obj` to `fn`.
         *
         * @param {Object} obj
         * @param {Function|String} fn or string
         * @return {Function}
         * @api public
         */

        module.exports = function(obj, fn){
            if ('string' == typeof fn) fn = obj[fn];
            if ('function' != typeof fn) throw new Error('bind() requires a function');
            var args = slice.call(arguments, 2);
            return function(){
                return fn.apply(obj, args.concat(slice.call(arguments)));
            }
        };

    },{}],9:[function(require,module,exports){

        /**
         * Expose `Emitter`.
         */

        if (typeof module !== 'undefined') {
            module.exports = Emitter;
        }

        /**
         * Initialize a new `Emitter`.
         *
         * @api public
         */

        function Emitter(obj) {
            if (obj) return mixin(obj);
        };

        /**
         * Mixin the emitter properties.
         *
         * @param {Object} obj
         * @return {Object}
         * @api private
         */

        function mixin(obj) {
            for (var key in Emitter.prototype) {
                obj[key] = Emitter.prototype[key];
            }
            return obj;
        }

        /**
         * Listen on the given `event` with `fn`.
         *
         * @param {String} event
         * @param {Function} fn
         * @return {Emitter}
         * @api public
         */

        Emitter.prototype.on =
            Emitter.prototype.addEventListener = function(event, fn){
                this._callbacks = this._callbacks || {};
                (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
                    .push(fn);
                return this;
            };

        /**
         * Adds an `event` listener that will be invoked a single
         * time then automatically removed.
         *
         * @param {String} event
         * @param {Function} fn
         * @return {Emitter}
         * @api public
         */

        Emitter.prototype.once = function(event, fn){
            function on() {
                this.off(event, on);
                fn.apply(this, arguments);
            }

            on.fn = fn;
            this.on(event, on);
            return this;
        };

        /**
         * Remove the given callback for `event` or all
         * registered callbacks.
         *
         * @param {String} event
         * @param {Function} fn
         * @return {Emitter}
         * @api public
         */

        Emitter.prototype.off =
            Emitter.prototype.removeListener =
                Emitter.prototype.removeAllListeners =
                    Emitter.prototype.removeEventListener = function(event, fn){
                        this._callbacks = this._callbacks || {};

                        // all
                        if (0 == arguments.length) {
                            this._callbacks = {};
                            return this;
                        }

                        // specific event
                        var callbacks = this._callbacks['$' + event];
                        if (!callbacks) return this;

                        // remove all handlers
                        if (1 == arguments.length) {
                            delete this._callbacks['$' + event];
                            return this;
                        }

                        // remove specific handler
                        var cb;
                        for (var i = 0; i < callbacks.length; i++) {
                            cb = callbacks[i];
                            if (cb === fn || cb.fn === fn) {
                                callbacks.splice(i, 1);
                                break;
                            }
                        }
                        return this;
                    };

        /**
         * Emit `event` with the given args.
         *
         * @param {String} event
         * @param {Mixed} ...
         * @return {Emitter}
         */

        Emitter.prototype.emit = function(event){
            this._callbacks = this._callbacks || {};
            var args = [].slice.call(arguments, 1)
                , callbacks = this._callbacks['$' + event];

            if (callbacks) {
                callbacks = callbacks.slice(0);
                for (var i = 0, len = callbacks.length; i < len; ++i) {
                    callbacks[i].apply(this, args);
                }
            }

            return this;
        };

        /**
         * Return array of callbacks for `event`.
         *
         * @param {String} event
         * @return {Array}
         * @api public
         */

        Emitter.prototype.listeners = function(event){
            this._callbacks = this._callbacks || {};
            return this._callbacks['$' + event] || [];
        };

        /**
         * Check if this emitter has `event` handlers.
         *
         * @param {String} event
         * @return {Boolean}
         * @api public
         */

        Emitter.prototype.hasListeners = function(event){
            return !! this.listeners(event).length;
        };

    },{}],10:[function(require,module,exports){

        module.exports = function(a, b){
            var fn = function(){};
            fn.prototype = b.prototype;
            a.prototype = new fn;
            a.prototype.constructor = a;
        };
    },{}],11:[function(require,module,exports){
        /**
         * cuid.js
         * Collision-resistant UID generator for browsers and node.
         * Sequential for fast db lookups and recency sorting.
         * Safe for element IDs and server-side lookups.
         *
         * Extracted from CLCTR
         *
         * Copyright (c) Eric Elliott 2012
         * MIT License
         */

        var fingerprint = require('./lib/fingerprint.js');
        var pad = require('./lib/pad.js');

        var c = 0,
            blockSize = 4,
            base = 36,
            discreteValues = Math.pow(base, blockSize);

        function randomBlock () {
            return pad((Math.random() *
                discreteValues << 0)
                .toString(base), blockSize);
        }

        function safeCounter () {
            c = c < discreteValues ? c : 0;
            c++; // this is not subliminal
            return c - 1;
        }

        function cuid () {
            // Starting with a lowercase letter makes
            // it HTML element ID friendly.
            var letter = 'c', // hard-coded allows for sequential access

                // timestamp
                // warning: this exposes the exact date and time
                // that the uid was created.
                timestamp = (new Date().getTime()).toString(base),

                // Prevent same-machine collisions.
                counter = pad(safeCounter().toString(base), blockSize),

                // A few chars to generate distinct ids for different
                // clients (so different computers are far less
                // likely to generate the same id)
                print = fingerprint(),

                // Grab some more chars from Math.random()
                random = randomBlock() + randomBlock();

            return letter + timestamp + counter + print + random;
        }

        cuid.slug = function slug () {
            var date = new Date().getTime().toString(36),
                counter = safeCounter().toString(36).slice(-4),
                print = fingerprint().slice(0, 1) +
                    fingerprint().slice(-1),
                random = randomBlock().slice(-2);

            return date.slice(-2) +
                counter + print + random;
        };

        cuid.fingerprint = fingerprint;

        module.exports = cuid;

    },{"./lib/fingerprint.js":12,"./lib/pad.js":13}],12:[function(require,module,exports){
        var pad = require('./pad.js');

        var env = typeof window === 'object' ? window : self;
        var globalCount = Object.keys(env);
        var mimeTypesLength = navigator.mimeTypes ? navigator.mimeTypes.length : 0;
        var clientId = pad((mimeTypesLength +
            navigator.userAgent.length).toString(36) +
            globalCount.toString(36), 4);

        module.exports = function fingerprint () {
            return clientId;
        };

    },{"./pad.js":13}],13:[function(require,module,exports){
        module.exports = function pad (num, size) {
            var s = '000000000' + num;
            return s.substr(s.length - size);
        };

    },{}],14:[function(require,module,exports){
        (function (process){
            /**
             * This is the web browser implementation of `debug()`.
             *
             * Expose `debug()` as the module.
             */

            exports = module.exports = require('./debug');
            exports.log = log;
            exports.formatArgs = formatArgs;
            exports.save = save;
            exports.load = load;
            exports.useColors = useColors;
            exports.storage = 'undefined' != typeof chrome
            && 'undefined' != typeof chrome.storage
                ? chrome.storage.local
                : localstorage();

            /**
             * Colors.
             */

            exports.colors = [
                'lightseagreen',
                'forestgreen',
                'goldenrod',
                'dodgerblue',
                'darkorchid',
                'crimson'
            ];

            /**
             * Currently only WebKit-based Web Inspectors, Firefox >= v31,
             * and the Firebug extension (any Firefox version) are known
             * to support "%c" CSS customizations.
             *
             * TODO: add a `localStorage` variable to explicitly enable/disable colors
             */

            function useColors() {
                // NB: In an Electron preload script, document will be defined but not fully
                // initialized. Since we know we're in Chrome, we'll just detect this case
                // explicitly
                if (typeof window !== 'undefined' && window && typeof window.process !== 'undefined' && window.process.type === 'renderer') {
                    return true;
                }

                // is webkit? http://stackoverflow.com/a/16459606/376773
                // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
                return (typeof document !== 'undefined' && document && 'WebkitAppearance' in document.documentElement.style) ||
                    // is firebug? http://stackoverflow.com/a/398120/376773
                    (typeof window !== 'undefined' && window && window.console && (console.firebug || (console.exception && console.table))) ||
                    // is firefox >= v31?
                    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
                    (typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
                    // double check webkit in userAgent just in case we are in a worker
                    (typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
            }

            /**
             * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
             */

            exports.formatters.j = function(v) {
                try {
                    return JSON.stringify(v);
                } catch (err) {
                    return '[UnexpectedJSONParseError]: ' + err.message;
                }
            };


            /**
             * Colorize log arguments if enabled.
             *
             * @api public
             */

            function formatArgs(args) {
                var useColors = this.useColors;

                args[0] = (useColors ? '%c' : '')
                    + this.namespace
                    + (useColors ? ' %c' : ' ')
                    + args[0]
                    + (useColors ? '%c ' : ' ')
                    + '+' + exports.humanize(this.diff);

                if (!useColors) return;

                var c = 'color: ' + this.color;
                args.splice(1, 0, c, 'color: inherit')

                // the final "%c" is somewhat tricky, because there could be other
                // arguments passed either before or after the %c, so we need to
                // figure out the correct index to insert the CSS into
                var index = 0;
                var lastC = 0;
                args[0].replace(/%[a-zA-Z%]/g, function(match) {
                    if ('%%' === match) return;
                    index++;
                    if ('%c' === match) {
                        // we only are interested in the *last* %c
                        // (the user may have provided their own)
                        lastC = index;
                    }
                });

                args.splice(lastC, 0, c);
            }

            /**
             * Invokes `console.log()` when available.
             * No-op when `console.log` is not a "function".
             *
             * @api public
             */

            function log() {
                // this hackery is required for IE8/9, where
                // the `console.log` function doesn't have 'apply'
                return 'object' === typeof console
                    && console.log
                    && Function.prototype.apply.call(console.log, console, arguments);
            }

            /**
             * Save `namespaces`.
             *
             * @param {String} namespaces
             * @api private
             */

            function save(namespaces) {
                try {
                    if (null == namespaces) {
                        exports.storage.removeItem('debug');
                    } else {
                        exports.storage.debug = namespaces;
                    }
                } catch(e) {}
            }

            /**
             * Load `namespaces`.
             *
             * @return {String} returns the previously persisted debug modes
             * @api private
             */

            function load() {
                var r;
                try {
                    r = exports.storage.debug;
                } catch(e) {}

                // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
                if (!r && typeof process !== 'undefined' && 'env' in process) {
                    r = process.env.DEBUG;
                }

                return r;
            }

            /**
             * Enable namespaces listed in `localStorage.debug` initially.
             */

            exports.enable(load());

            /**
             * Localstorage attempts to return the localstorage.
             *
             * This is necessary because safari throws
             * when a user disables cookies/localstorage
             * and you attempt to access it.
             *
             * @return {LocalStorage}
             * @api private
             */

            function localstorage() {
                try {
                    return window.localStorage;
                } catch (e) {}
            }

        }).call(this,require('_process'))

    },{"./debug":15,"_process":6}],15:[function(require,module,exports){

        /**
         * This is the common logic for both the Node.js and web browser
         * implementations of `debug()`.
         *
         * Expose `debug()` as the module.
         */

        exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
        exports.coerce = coerce;
        exports.disable = disable;
        exports.enable = enable;
        exports.enabled = enabled;
        exports.humanize = require('ms');

        /**
         * The currently active debug mode names, and names to skip.
         */

        exports.names = [];
        exports.skips = [];

        /**
         * Map of special "%n" handling functions, for the debug "format" argument.
         *
         * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
         */

        exports.formatters = {};

        /**
         * Previous log timestamp.
         */

        var prevTime;

        /**
         * Select a color.
         * @param {String} namespace
         * @return {Number}
         * @api private
         */

        function selectColor(namespace) {
            var hash = 0, i;

            for (i in namespace) {
                hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);
                hash |= 0; // Convert to 32bit integer
            }

            return exports.colors[Math.abs(hash) % exports.colors.length];
        }

        /**
         * Create a debugger with the given `namespace`.
         *
         * @param {String} namespace
         * @return {Function}
         * @api public
         */

        function createDebug(namespace) {

            function debug() {
                // disabled?
                if (!debug.enabled) return;

                var self = debug;

                // set `diff` timestamp
                var curr = +new Date();
                var ms = curr - (prevTime || curr);
                self.diff = ms;
                self.prev = prevTime;
                self.curr = curr;
                prevTime = curr;

                // turn the `arguments` into a proper Array
                var args = new Array(arguments.length);
                for (var i = 0; i < args.length; i++) {
                    args[i] = arguments[i];
                }

                args[0] = exports.coerce(args[0]);

                if ('string' !== typeof args[0]) {
                    // anything else let's inspect with %O
                    args.unshift('%O');
                }

                // apply any `formatters` transformations
                var index = 0;
                args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
                    // if we encounter an escaped % then don't increase the array index
                    if (match === '%%') return match;
                    index++;
                    var formatter = exports.formatters[format];
                    if ('function' === typeof formatter) {
                        var val = args[index];
                        match = formatter.call(self, val);

                        // now we need to remove `args[index]` since it's inlined in the `format`
                        args.splice(index, 1);
                        index--;
                    }
                    return match;
                });

                // apply env-specific formatting (colors, etc.)
                exports.formatArgs.call(self, args);

                var logFn = debug.log || exports.log || console.log.bind(console);
                logFn.apply(self, args);
            }

            debug.namespace = namespace;
            debug.enabled = exports.enabled(namespace);
            debug.useColors = exports.useColors();
            debug.color = selectColor(namespace);

            // env-specific initialization logic for debug instances
            if ('function' === typeof exports.init) {
                exports.init(debug);
            }

            return debug;
        }

        /**
         * Enables a debug mode by namespaces. This can include modes
         * separated by a colon and wildcards.
         *
         * @param {String} namespaces
         * @api public
         */

        function enable(namespaces) {
            exports.save(namespaces);

            exports.names = [];
            exports.skips = [];

            var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
            var len = split.length;

            for (var i = 0; i < len; i++) {
                if (!split[i]) continue; // ignore empty strings
                namespaces = split[i].replace(/\*/g, '.*?');
                if (namespaces[0] === '-') {
                    exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
                } else {
                    exports.names.push(new RegExp('^' + namespaces + '$'));
                }
            }
        }

        /**
         * Disable debug output.
         *
         * @api public
         */

        function disable() {
            exports.enable('');
        }

        /**
         * Returns true if the given mode name is enabled, false otherwise.
         *
         * @param {String} name
         * @return {Boolean}
         * @api public
         */

        function enabled(name) {
            var i, len;
            for (i = 0, len = exports.skips.length; i < len; i++) {
                if (exports.skips[i].test(name)) {
                    return false;
                }
            }
            for (i = 0, len = exports.names.length; i < len; i++) {
                if (exports.names[i].test(name)) {
                    return true;
                }
            }
            return false;
        }

        /**
         * Coerce `val`.
         *
         * @param {Mixed} val
         * @return {Mixed}
         * @api private
         */

        function coerce(val) {
            if (val instanceof Error) return val.stack || val.message;
            return val;
        }

    },{"ms":42}],16:[function(require,module,exports){
        module.exports = dragDrop

        var flatten = require('flatten')
        var parallel = require('run-parallel')

        function dragDrop (elem, listeners) {
            if (typeof elem === 'string') {
                var selector = elem
                elem = window.document.querySelector(elem)
                if (!elem) {
                    throw new Error('"' + selector + '" does not match any HTML elements')
                }
            }

            if (!elem) {
                throw new Error('"' + elem + '" is not a valid HTML element')
            }

            if (typeof listeners === 'function') {
                listeners = { onDrop: listeners }
            }

            var timeout

            elem.addEventListener('dragenter', onDragEnter, false)
            elem.addEventListener('dragover', onDragOver, false)
            elem.addEventListener('dragleave', onDragLeave, false)
            elem.addEventListener('drop', onDrop, false)

            // Function to remove drag-drop listeners
            return function remove () {
                removeDragClass()
                elem.removeEventListener('dragenter', onDragEnter, false)
                elem.removeEventListener('dragover', onDragOver, false)
                elem.removeEventListener('dragleave', onDragLeave, false)
                elem.removeEventListener('drop', onDrop, false)
            }

            function onDragEnter (e) {
                if (listeners.onDragEnter) {
                    listeners.onDragEnter(e)
                }

                // Prevent event
                e.stopPropagation()
                e.preventDefault()
                return false
            }

            function onDragOver (e) {
                e.stopPropagation()
                e.preventDefault()
                if (e.dataTransfer.items) {
                    // Only add "drag" class when `items` contains items that are able to be
                    // handled by the registered listeners (files vs. text)
                    var items = toArray(e.dataTransfer.items)
                    var fileItems = items.filter(function (item) { return item.kind === 'file' })
                    var textItems = items.filter(function (item) { return item.kind === 'string' })

                    if (fileItems.length === 0 && !listeners.onDropText) return
                    if (textItems.length === 0 && !listeners.onDrop) return
                    if (fileItems.length === 0 && textItems.length === 0) return
                }

                elem.classList.add('drag')
                clearTimeout(timeout)

                if (listeners.onDragOver) {
                    listeners.onDragOver(e)
                }

                e.dataTransfer.dropEffect = 'copy'
                return false
            }

            function onDragLeave (e) {
                e.stopPropagation()
                e.preventDefault()

                if (listeners.onDragLeave) {
                    listeners.onDragLeave(e)
                }

                clearTimeout(timeout)
                timeout = setTimeout(removeDragClass, 50)

                return false
            }

            function onDrop (e) {
                e.stopPropagation()
                e.preventDefault()

                if (listeners.onDragLeave) {
                    listeners.onDragLeave(e)
                }

                clearTimeout(timeout)
                removeDragClass()

                var pos = {
                    x: e.clientX,
                    y: e.clientY
                }

                // text drop support
                var text = e.dataTransfer.getData('text')
                if (text && listeners.onDropText) {
                    listeners.onDropText(text, pos)
                }

                // file drop support
                if (e.dataTransfer.items) {
                    // Handle directories in Chrome using the proprietary FileSystem API
                    var items = toArray(e.dataTransfer.items).filter(function (item) {
                        return item.kind === 'file'
                    })

                    if (items.length === 0) return

                    parallel(items.map(function (item) {
                        return function (cb) {
                            processEntry(item.webkitGetAsEntry(), cb)
                        }
                    }), function (err, results) {
                        // This catches permission errors with file:// in Chrome. This should never
                        // throw in production code, so the user does not need to use try-catch.
                        if (err) throw err
                        if (listeners.onDrop) {
                            listeners.onDrop(flatten(results), pos)
                        }
                    })
                } else {
                    var files = toArray(e.dataTransfer.files)

                    if (files.length === 0) return

                    files.forEach(function (file) {
                        file.fullPath = '/' + file.name
                    })

                    if (listeners.onDrop) {
                        listeners.onDrop(files, pos)
                    }
                }

                return false
            }

            function removeDragClass () {
                elem.classList.remove('drag')
            }
        }

        function processEntry (entry, cb) {
            var entries = []

            if (entry.isFile) {
                entry.file(function (file) {
                    file.fullPath = entry.fullPath  // preserve pathing for consumer
                    cb(null, file)
                }, function (err) {
                    cb(err)
                })
            } else if (entry.isDirectory) {
                var reader = entry.createReader()
                readEntries()
            }

            function readEntries () {
                reader.readEntries(function (entries_) {
                    if (entries_.length > 0) {
                        entries = entries.concat(toArray(entries_))
                        readEntries() // continue reading entries until `readEntries` returns no more
                    } else {
                        doneEntries()
                    }
                })
            }

            function doneEntries () {
                parallel(entries.map(function (entry) {
                    return function (cb) {
                        processEntry(entry, cb)
                    }
                }), cb)
            }
        }

        function toArray (list) {
            return Array.prototype.slice.call(list || [], 0)
        }

    },{"flatten":35,"run-parallel":51}],17:[function(require,module,exports){

        module.exports = require('./socket');

        /**
         * Exports parser
         *
         * @api public
         *
         */
        module.exports.parser = require('engine.io-parser');

    },{"./socket":18,"engine.io-parser":29}],18:[function(require,module,exports){
        (function (global){
            /**
             * Module dependencies.
             */

            var transports = require('./transports/index');
            var Emitter = require('component-emitter');
            var debug = require('debug')('engine.io-client:socket');
            var index = require('indexof');
            var parser = require('engine.io-parser');
            var parseuri = require('parseuri');
            var parseqs = require('parseqs');

            /**
             * Module exports.
             */

            module.exports = Socket;

            /**
             * Socket constructor.
             *
             * @param {String|Object} uri or options
             * @param {Object} options
             * @api public
             */

            function Socket (uri, opts) {
                if (!(this instanceof Socket)) return new Socket(uri, opts);

                opts = opts || {};

                if (uri && 'object' === typeof uri) {
                    opts = uri;
                    uri = null;
                }

                if (uri) {
                    uri = parseuri(uri);
                    opts.hostname = uri.host;
                    opts.secure = uri.protocol === 'https' || uri.protocol === 'wss';
                    opts.port = uri.port;
                    if (uri.query) opts.query = uri.query;
                } else if (opts.host) {
                    opts.hostname = parseuri(opts.host).host;
                }

                this.secure = null != opts.secure ? opts.secure
                    : (global.location && 'https:' === location.protocol);

                if (opts.hostname && !opts.port) {
                    // if no port is specified manually, use the protocol default
                    opts.port = this.secure ? '443' : '80';
                }

                this.agent = opts.agent || false;
                this.hostname = opts.hostname ||
                    (global.location ? location.hostname : 'localhost');
                this.port = opts.port || (global.location && location.port
                    ? location.port
                    : (this.secure ? 443 : 80));
                this.query = opts.query || {};
                if ('string' === typeof this.query) this.query = parseqs.decode(this.query);
                this.upgrade = false !== opts.upgrade;
                this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
                this.forceJSONP = !!opts.forceJSONP;
                this.jsonp = false !== opts.jsonp;
                this.forceBase64 = !!opts.forceBase64;
                this.enablesXDR = !!opts.enablesXDR;
                this.timestampParam = opts.timestampParam || 't';
                this.timestampRequests = opts.timestampRequests;
                this.transports = opts.transports || ['polling', 'websocket'];
                this.transportOptions = opts.transportOptions || {};
                this.readyState = '';
                this.writeBuffer = [];
                this.prevBufferLen = 0;
                this.policyPort = opts.policyPort || 843;
                this.rememberUpgrade = opts.rememberUpgrade || false;
                this.binaryType = null;
                this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
                this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || {}) : false;

                if (true === this.perMessageDeflate) this.perMessageDeflate = {};
                if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) {
                    this.perMessageDeflate.threshold = 1024;
                }

                // SSL options for Node.js client
                this.pfx = opts.pfx || null;
                this.key = opts.key || null;
                this.passphrase = opts.passphrase || null;
                this.cert = opts.cert || null;
                this.ca = opts.ca || null;
                this.ciphers = opts.ciphers || null;
                this.rejectUnauthorized = opts.rejectUnauthorized === undefined ? true : opts.rejectUnauthorized;
                this.forceNode = !!opts.forceNode;

                // other options for Node.js client
                var freeGlobal = typeof global === 'object' && global;
                if (freeGlobal.global === freeGlobal) {
                    if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) {
                        this.extraHeaders = opts.extraHeaders;
                    }

                    if (opts.localAddress) {
                        this.localAddress = opts.localAddress;
                    }
                }

                // set on handshake
                this.id = null;
                this.upgrades = null;
                this.pingInterval = null;
                this.pingTimeout = null;

                // set on heartbeat
                this.pingIntervalTimer = null;
                this.pingTimeoutTimer = null;

                this.open();
            }

            Socket.priorWebsocketSuccess = false;

            /**
             * Mix in `Emitter`.
             */

            Emitter(Socket.prototype);

            /**
             * Protocol version.
             *
             * @api public
             */

            Socket.protocol = parser.protocol; // this is an int

            /**
             * Expose deps for legacy compatibility
             * and standalone browser access.
             */

            Socket.Socket = Socket;
            Socket.Transport = require('./transport');
            Socket.transports = require('./transports/index');
            Socket.parser = require('engine.io-parser');

            /**
             * Creates transport of the given type.
             *
             * @param {String} transport name
             * @return {Transport}
             * @api private
             */

            Socket.prototype.createTransport = function (name) {
                debug('creating transport "%s"', name);
                var query = clone(this.query);

                // append engine.io protocol identifier
                query.EIO = parser.protocol;

                // transport name
                query.transport = name;

                // per-transport options
                var options = this.transportOptions[name] || {};

                // session id if we already have one
                if (this.id) query.sid = this.id;

                var transport = new transports[name]({
                    query: query,
                    socket: this,
                    agent: options.agent || this.agent,
                    hostname: options.hostname || this.hostname,
                    port: options.port || this.port,
                    secure: options.secure || this.secure,
                    path: options.path || this.path,
                    forceJSONP: options.forceJSONP || this.forceJSONP,
                    jsonp: options.jsonp || this.jsonp,
                    forceBase64: options.forceBase64 || this.forceBase64,
                    enablesXDR: options.enablesXDR || this.enablesXDR,
                    timestampRequests: options.timestampRequests || this.timestampRequests,
                    timestampParam: options.timestampParam || this.timestampParam,
                    policyPort: options.policyPort || this.policyPort,
                    pfx: options.pfx || this.pfx,
                    key: options.key || this.key,
                    passphrase: options.passphrase || this.passphrase,
                    cert: options.cert || this.cert,
                    ca: options.ca || this.ca,
                    ciphers: options.ciphers || this.ciphers,
                    rejectUnauthorized: options.rejectUnauthorized || this.rejectUnauthorized,
                    perMessageDeflate: options.perMessageDeflate || this.perMessageDeflate,
                    extraHeaders: options.extraHeaders || this.extraHeaders,
                    forceNode: options.forceNode || this.forceNode,
                    localAddress: options.localAddress || this.localAddress,
                    requestTimeout: options.requestTimeout || this.requestTimeout,
                    protocols: options.protocols || void (0)
                });

                return transport;
            };

            function clone (obj) {
                var o = {};
                for (var i in obj) {
                    if (obj.hasOwnProperty(i)) {
                        o[i] = obj[i];
                    }
                }
                return o;
            }

            /**
             * Initializes transport to use and starts probe.
             *
             * @api private
             */
            Socket.prototype.open = function () {
                var transport;
                if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') !== -1) {
                    transport = 'websocket';
                } else if (0 === this.transports.length) {
                    // Emit error on next tick so it can be listened to
                    var self = this;
                    setTimeout(function () {
                        self.emit('error', 'No transports available');
                    }, 0);
                    return;
                } else {
                    transport = this.transports[0];
                }
                this.readyState = 'opening';

                // Retry with the next transport if the transport is disabled (jsonp: false)
                try {
                    transport = this.createTransport(transport);
                } catch (e) {
                    this.transports.shift();
                    this.open();
                    return;
                }

                transport.open();
                this.setTransport(transport);
            };

            /**
             * Sets the current transport. Disables the existing one (if any).
             *
             * @api private
             */

            Socket.prototype.setTransport = function (transport) {
                debug('setting transport %s', transport.name);
                var self = this;

                if (this.transport) {
                    debug('clearing existing transport %s', this.transport.name);
                    this.transport.removeAllListeners();
                }

                // set up transport
                this.transport = transport;

                // set up transport listeners
                transport
                    .on('drain', function () {
                        self.onDrain();
                    })
                    .on('packet', function (packet) {
                        self.onPacket(packet);
                    })
                    .on('error', function (e) {
                        self.onError(e);
                    })
                    .on('close', function () {
                        self.onClose('transport close');
                    });
            };

            /**
             * Probes a transport.
             *
             * @param {String} transport name
             * @api private
             */

            Socket.prototype.probe = function (name) {
                debug('probing transport "%s"', name);
                var transport = this.createTransport(name, { probe: 1 });
                var failed = false;
                var self = this;

                Socket.priorWebsocketSuccess = false;

                function onTransportOpen () {
                    if (self.onlyBinaryUpgrades) {
                        var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
                        failed = failed || upgradeLosesBinary;
                    }
                    if (failed) return;

                    debug('probe transport "%s" opened', name);
                    transport.send([{ type: 'ping', data: 'probe' }]);
                    transport.once('packet', function (msg) {
                        if (failed) return;
                        if ('pong' === msg.type && 'probe' === msg.data) {
                            debug('probe transport "%s" pong', name);
                            self.upgrading = true;
                            self.emit('upgrading', transport);
                            if (!transport) return;
                            Socket.priorWebsocketSuccess = 'websocket' === transport.name;

                            debug('pausing current transport "%s"', self.transport.name);
                            self.transport.pause(function () {
                                if (failed) return;
                                if ('closed' === self.readyState) return;
                                debug('changing transport and sending upgrade packet');

                                cleanup();

                                self.setTransport(transport);
                                transport.send([{ type: 'upgrade' }]);
                                self.emit('upgrade', transport);
                                transport = null;
                                self.upgrading = false;
                                self.flush();
                            });
                        } else {
                            debug('probe transport "%s" failed', name);
                            var err = new Error('probe error');
                            err.transport = transport.name;
                            self.emit('upgradeError', err);
                        }
                    });
                }

                function freezeTransport () {
                    if (failed) return;

                    // Any callback called by transport should be ignored since now
                    failed = true;

                    cleanup();

                    transport.close();
                    transport = null;
                }

                // Handle any error that happens while probing
                function onerror (err) {
                    var error = new Error('probe error: ' + err);
                    error.transport = transport.name;

                    freezeTransport();

                    debug('probe transport "%s" failed because of error: %s', name, err);

                    self.emit('upgradeError', error);
                }

                function onTransportClose () {
                    onerror('transport closed');
                }

                // When the socket is closed while we're probing
                function onclose () {
                    onerror('socket closed');
                }

                // When the socket is upgraded while we're probing
                function onupgrade (to) {
                    if (transport && to.name !== transport.name) {
                        debug('"%s" works - aborting "%s"', to.name, transport.name);
                        freezeTransport();
                    }
                }

                // Remove all listeners on the transport and on self
                function cleanup () {
                    transport.removeListener('open', onTransportOpen);
                    transport.removeListener('error', onerror);
                    transport.removeListener('close', onTransportClose);
                    self.removeListener('close', onclose);
                    self.removeListener('upgrading', onupgrade);
                }

                transport.once('open', onTransportOpen);
                transport.once('error', onerror);
                transport.once('close', onTransportClose);

                this.once('close', onclose);
                this.once('upgrading', onupgrade);

                transport.open();
            };

            /**
             * Called when connection is deemed open.
             *
             * @api public
             */

            Socket.prototype.onOpen = function () {
                debug('socket open');
                this.readyState = 'open';
                Socket.priorWebsocketSuccess = 'websocket' === this.transport.name;
                this.emit('open');
                this.flush();

                // we check for `readyState` in case an `open`
                // listener already closed the socket
                if ('open' === this.readyState && this.upgrade && this.transport.pause) {
                    debug('starting upgrade probes');
                    for (var i = 0, l = this.upgrades.length; i < l; i++) {
                        this.probe(this.upgrades[i]);
                    }
                }
            };

            /**
             * Handles a packet.
             *
             * @api private
             */

            Socket.prototype.onPacket = function (packet) {
                if ('opening' === this.readyState || 'open' === this.readyState ||
                    'closing' === this.readyState) {
                    debug('socket receive: type "%s", data "%s"', packet.type, packet.data);

                    this.emit('packet', packet);

                    // Socket is live - any packet counts
                    this.emit('heartbeat');

                    switch (packet.type) {
                        case 'open':
                            this.onHandshake(JSON.parse(packet.data));
                            break;

                        case 'pong':
                            this.setPing();
                            this.emit('pong');
                            break;

                        case 'error':
                            var err = new Error('server error');
                            err.code = packet.data;
                            this.onError(err);
                            break;

                        case 'message':
                            this.emit('data', packet.data);
                            this.emit('message', packet.data);
                            break;
                    }
                } else {
                    debug('packet received with socket readyState "%s"', this.readyState);
                }
            };

            /**
             * Called upon handshake completion.
             *
             * @param {Object} handshake obj
             * @api private
             */

            Socket.prototype.onHandshake = function (data) {
                this.emit('handshake', data);
                this.id = data.sid;
                this.transport.query.sid = data.sid;
                this.upgrades = this.filterUpgrades(data.upgrades);
                this.pingInterval = data.pingInterval;
                this.pingTimeout = data.pingTimeout;
                this.onOpen();
                // In case open handler closes socket
                if ('closed' === this.readyState) return;
                this.setPing();

                // Prolong liveness of socket on heartbeat
                this.removeListener('heartbeat', this.onHeartbeat);
                this.on('heartbeat', this.onHeartbeat);
            };

            /**
             * Resets ping timeout.
             *
             * @api private
             */

            Socket.prototype.onHeartbeat = function (timeout) {
                clearTimeout(this.pingTimeoutTimer);
                var self = this;
                self.pingTimeoutTimer = setTimeout(function () {
                    if ('closed' === self.readyState) return;
                    self.onClose('ping timeout');
                }, timeout || (self.pingInterval + self.pingTimeout));
            };

            /**
             * Pings server every `this.pingInterval` and expects response
             * within `this.pingTimeout` or closes connection.
             *
             * @api private
             */

            Socket.prototype.setPing = function () {
                var self = this;
                clearTimeout(self.pingIntervalTimer);
                self.pingIntervalTimer = setTimeout(function () {
                    debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
                    self.ping();
                    self.onHeartbeat(self.pingTimeout);
                }, self.pingInterval);
            };

            /**
             * Sends a ping packet.
             *
             * @api private
             */

            Socket.prototype.ping = function () {
                var self = this;
                this.sendPacket('ping', function () {
                    self.emit('ping');
                });
            };

            /**
             * Called on `drain` event
             *
             * @api private
             */

            Socket.prototype.onDrain = function () {
                this.writeBuffer.splice(0, this.prevBufferLen);

                // setting prevBufferLen = 0 is very important
                // for example, when upgrading, upgrade packet is sent over,
                // and a nonzero prevBufferLen could cause problems on `drain`
                this.prevBufferLen = 0;

                if (0 === this.writeBuffer.length) {
                    this.emit('drain');
                } else {
                    this.flush();
                }
            };

            /**
             * Flush write buffers.
             *
             * @api private
             */

            Socket.prototype.flush = function () {
                if ('closed' !== this.readyState && this.transport.writable &&
                    !this.upgrading && this.writeBuffer.length) {
                    debug('flushing %d packets in socket', this.writeBuffer.length);
                    this.transport.send(this.writeBuffer);
                    // keep track of current length of writeBuffer
                    // splice writeBuffer and callbackBuffer on `drain`
                    this.prevBufferLen = this.writeBuffer.length;
                    this.emit('flush');
                }
            };

            /**
             * Sends a message.
             *
             * @param {String} message.
             * @param {Function} callback function.
             * @param {Object} options.
             * @return {Socket} for chaining.
             * @api public
             */

            Socket.prototype.write =
                Socket.prototype.send = function (msg, options, fn) {
                    this.sendPacket('message', msg, options, fn);
                    return this;
                };

            /**
             * Sends a packet.
             *
             * @param {String} packet type.
             * @param {String} data.
             * @param {Object} options.
             * @param {Function} callback function.
             * @api private
             */

            Socket.prototype.sendPacket = function (type, data, options, fn) {
                if ('function' === typeof data) {
                    fn = data;
                    data = undefined;
                }

                if ('function' === typeof options) {
                    fn = options;
                    options = null;
                }

                if ('closing' === this.readyState || 'closed' === this.readyState) {
                    return;
                }

                options = options || {};
                options.compress = false !== options.compress;

                var packet = {
                    type: type,
                    data: data,
                    options: options
                };
                this.emit('packetCreate', packet);
                this.writeBuffer.push(packet);
                if (fn) this.once('flush', fn);
                this.flush();
            };

            /**
             * Closes the connection.
             *
             * @api private
             */

            Socket.prototype.close = function () {
                if ('opening' === this.readyState || 'open' === this.readyState) {
                    this.readyState = 'closing';

                    var self = this;

                    if (this.writeBuffer.length) {
                        this.once('drain', function () {
                            if (this.upgrading) {
                                waitForUpgrade();
                            } else {
                                close();
                            }
                        });
                    } else if (this.upgrading) {
                        waitForUpgrade();
                    } else {
                        close();
                    }
                }

                function close () {
                    self.onClose('forced close');
                    debug('socket closing - telling transport to close');
                    self.transport.close();
                }

                function cleanupAndClose () {
                    self.removeListener('upgrade', cleanupAndClose);
                    self.removeListener('upgradeError', cleanupAndClose);
                    close();
                }

                function waitForUpgrade () {
                    // wait for upgrade to finish since we can't send packets while pausing a transport
                    self.once('upgrade', cleanupAndClose);
                    self.once('upgradeError', cleanupAndClose);
                }

                return this;
            };

            /**
             * Called upon transport error
             *
             * @api private
             */

            Socket.prototype.onError = function (err) {
                debug('socket error %j', err);
                Socket.priorWebsocketSuccess = false;
                this.emit('error', err);
                this.onClose('transport error', err);
            };

            /**
             * Called upon transport close.
             *
             * @api private
             */

            Socket.prototype.onClose = function (reason, desc) {
                if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) {
                    debug('socket close with reason: "%s"', reason);
                    var self = this;

                    // clear timers
                    clearTimeout(this.pingIntervalTimer);
                    clearTimeout(this.pingTimeoutTimer);

                    // stop event from firing again for transport
                    this.transport.removeAllListeners('close');

                    // ensure transport won't stay open
                    this.transport.close();

                    // ignore further transport communication
                    this.transport.removeAllListeners();

                    // set ready state
                    this.readyState = 'closed';

                    // clear session id
                    this.id = null;

                    // emit close event
                    this.emit('close', reason, desc);

                    // clean buffers after, so users can still
                    // grab the buffers on `close` event
                    self.writeBuffer = [];
                    self.prevBufferLen = 0;
                }
            };

            /**
             * Filters upgrades, returning only those matching client transports.
             *
             * @param {Array} server upgrades
             * @api private
             *
             */

            Socket.prototype.filterUpgrades = function (upgrades) {
                var filteredUpgrades = [];
                for (var i = 0, j = upgrades.length; i < j; i++) {
                    if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
                }
                return filteredUpgrades;
            };

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"./transport":19,"./transports/index":20,"component-emitter":9,"debug":26,"engine.io-parser":29,"indexof":38,"parseqs":44,"parseuri":45}],19:[function(require,module,exports){
        /**
         * Module dependencies.
         */

        var parser = require('engine.io-parser');
        var Emitter = require('component-emitter');

        /**
         * Module exports.
         */

        module.exports = Transport;

        /**
         * Transport abstract constructor.
         *
         * @param {Object} options.
         * @api private
         */

        function Transport (opts) {
            this.path = opts.path;
            this.hostname = opts.hostname;
            this.port = opts.port;
            this.secure = opts.secure;
            this.query = opts.query;
            this.timestampParam = opts.timestampParam;
            this.timestampRequests = opts.timestampRequests;
            this.readyState = '';
            this.agent = opts.agent || false;
            this.socket = opts.socket;
            this.enablesXDR = opts.enablesXDR;

            // SSL options for Node.js client
            this.pfx = opts.pfx;
            this.key = opts.key;
            this.passphrase = opts.passphrase;
            this.cert = opts.cert;
            this.ca = opts.ca;
            this.ciphers = opts.ciphers;
            this.rejectUnauthorized = opts.rejectUnauthorized;
            this.forceNode = opts.forceNode;

            // other options for Node.js client
            this.extraHeaders = opts.extraHeaders;
            this.localAddress = opts.localAddress;
        }

        /**
         * Mix in `Emitter`.
         */

        Emitter(Transport.prototype);

        /**
         * Emits an error.
         *
         * @param {String} str
         * @return {Transport} for chaining
         * @api public
         */

        Transport.prototype.onError = function (msg, desc) {
            var err = new Error(msg);
            err.type = 'TransportError';
            err.description = desc;
            this.emit('error', err);
            return this;
        };

        /**
         * Opens the transport.
         *
         * @api public
         */

        Transport.prototype.open = function () {
            if ('closed' === this.readyState || '' === this.readyState) {
                this.readyState = 'opening';
                this.doOpen();
            }

            return this;
        };

        /**
         * Closes the transport.
         *
         * @api private
         */

        Transport.prototype.close = function () {
            if ('opening' === this.readyState || 'open' === this.readyState) {
                this.doClose();
                this.onClose();
            }

            return this;
        };

        /**
         * Sends multiple packets.
         *
         * @param {Array} packets
         * @api private
         */

        Transport.prototype.send = function (packets) {
            if ('open' === this.readyState) {
                this.write(packets);
            } else {
                throw new Error('Transport not open');
            }
        };

        /**
         * Called upon open
         *
         * @api private
         */

        Transport.prototype.onOpen = function () {
            this.readyState = 'open';
            this.writable = true;
            this.emit('open');
        };

        /**
         * Called with data.
         *
         * @param {String} data
         * @api private
         */

        Transport.prototype.onData = function (data) {
            var packet = parser.decodePacket(data, this.socket.binaryType);
            this.onPacket(packet);
        };

        /**
         * Called with a decoded packet.
         */

        Transport.prototype.onPacket = function (packet) {
            this.emit('packet', packet);
        };

        /**
         * Called upon close.
         *
         * @api private
         */

        Transport.prototype.onClose = function () {
            this.readyState = 'closed';
            this.emit('close');
        };

    },{"component-emitter":9,"engine.io-parser":29}],20:[function(require,module,exports){
        (function (global){
            /**
             * Module dependencies
             */

            var XMLHttpRequest = require('xmlhttprequest-ssl');
            var XHR = require('./polling-xhr');
            var JSONP = require('./polling-jsonp');
            var websocket = require('./websocket');

            /**
             * Export transports.
             */

            exports.polling = polling;
            exports.websocket = websocket;

            /**
             * Polling transport polymorphic constructor.
             * Decides on xhr vs jsonp based on feature detection.
             *
             * @api private
             */

            function polling (opts) {
                var xhr;
                var xd = false;
                var xs = false;
                var jsonp = false !== opts.jsonp;

                if (global.location) {
                    var isSSL = 'https:' === location.protocol;
                    var port = location.port;

                    // some user agents have empty `location.port`
                    if (!port) {
                        port = isSSL ? 443 : 80;
                    }

                    xd = opts.hostname !== location.hostname || port !== opts.port;
                    xs = opts.secure !== isSSL;
                }

                opts.xdomain = xd;
                opts.xscheme = xs;
                xhr = new XMLHttpRequest(opts);

                if ('open' in xhr && !opts.forceJSONP) {
                    return new XHR(opts);
                } else {
                    if (!jsonp) throw new Error('JSONP disabled');
                    return new JSONP(opts);
                }
            }

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"./polling-jsonp":21,"./polling-xhr":22,"./websocket":24,"xmlhttprequest-ssl":25}],21:[function(require,module,exports){
        (function (global){

            /**
             * Module requirements.
             */

            var Polling = require('./polling');
            var inherit = require('component-inherit');

            /**
             * Module exports.
             */

            module.exports = JSONPPolling;

            /**
             * Cached regular expressions.
             */

            var rNewline = /\n/g;
            var rEscapedNewline = /\\n/g;

            /**
             * Global JSONP callbacks.
             */

            var callbacks;

            /**
             * Noop.
             */

            function empty () { }

            /**
             * JSONP Polling constructor.
             *
             * @param {Object} opts.
             * @api public
             */

            function JSONPPolling (opts) {
                Polling.call(this, opts);

                this.query = this.query || {};

                // define global callbacks array if not present
                // we do this here (lazily) to avoid unneeded global pollution
                if (!callbacks) {
                    // we need to consider multiple engines in the same page
                    if (!global.___eio) global.___eio = [];
                    callbacks = global.___eio;
                }

                // callback identifier
                this.index = callbacks.length;

                // add callback to jsonp global
                var self = this;
                callbacks.push(function (msg) {
                    self.onData(msg);
                });

                // append to query string
                this.query.j = this.index;

                // prevent spurious errors from being emitted when the window is unloaded
                if (global.document && global.addEventListener) {
                    global.addEventListener('beforeunload', function () {
                        if (self.script) self.script.onerror = empty;
                    }, false);
                }
            }

            /**
             * Inherits from Polling.
             */

            inherit(JSONPPolling, Polling);

            /*
 * JSONP only supports binary as base64 encoded strings
 */

            JSONPPolling.prototype.supportsBinary = false;

            /**
             * Closes the socket.
             *
             * @api private
             */

            JSONPPolling.prototype.doClose = function () {
                if (this.script) {
                    this.script.parentNode.removeChild(this.script);
                    this.script = null;
                }

                if (this.form) {
                    this.form.parentNode.removeChild(this.form);
                    this.form = null;
                    this.iframe = null;
                }

                Polling.prototype.doClose.call(this);
            };

            /**
             * Starts a poll cycle.
             *
             * @api private
             */

            JSONPPolling.prototype.doPoll = function () {
                var self = this;
                var script = document.createElement('script');

                if (this.script) {
                    this.script.parentNode.removeChild(this.script);
                    this.script = null;
                }

                script.async = true;
                script.src = this.uri();
                script.onerror = function (e) {
                    self.onError('jsonp poll error', e);
                };

                var insertAt = document.getElementsByTagName('script')[0];
                if (insertAt) {
                    insertAt.parentNode.insertBefore(script, insertAt);
                } else {
                    (document.head || document.body).appendChild(script);
                }
                this.script = script;

                var isUAgecko = 'undefined' !== typeof navigator && /gecko/i.test(navigator.userAgent);

                if (isUAgecko) {
                    setTimeout(function () {
                        var iframe = document.createElement('iframe');
                        document.body.appendChild(iframe);
                        document.body.removeChild(iframe);
                    }, 100);
                }
            };

            /**
             * Writes with a hidden iframe.
             *
             * @param {String} data to send
             * @param {Function} called upon flush.
             * @api private
             */

            JSONPPolling.prototype.doWrite = function (data, fn) {
                var self = this;

                if (!this.form) {
                    var form = document.createElement('form');
                    var area = document.createElement('textarea');
                    var id = this.iframeId = 'eio_iframe_' + this.index;
                    var iframe;

                    form.className = 'socketio';
                    form.style.position = 'absolute';
                    form.style.top = '-1000px';
                    form.style.left = '-1000px';
                    form.target = id;
                    form.method = 'POST';
                    form.setAttribute('accept-charset', 'utf-8');
                    area.name = 'd';
                    form.appendChild(area);
                    document.body.appendChild(form);

                    this.form = form;
                    this.area = area;
                }

                this.form.action = this.uri();

                function complete () {
                    initIframe();
                    fn();
                }

                function initIframe () {
                    if (self.iframe) {
                        try {
                            self.form.removeChild(self.iframe);
                        } catch (e) {
                            self.onError('jsonp polling iframe removal error', e);
                        }
                    }

                    try {
                        // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
                        var html = '<iframe src="javascript:0" name="' + self.iframeId + '">';
                        iframe = document.createElement(html);
                    } catch (e) {
                        iframe = document.createElement('iframe');
                        iframe.name = self.iframeId;
                        iframe.src = 'javascript:0';
                    }

                    iframe.id = self.iframeId;

                    self.form.appendChild(iframe);
                    self.iframe = iframe;
                }

                initIframe();

                // escape \n to prevent it from being converted into \r\n by some UAs
                // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
                data = data.replace(rEscapedNewline, '\\\n');
                this.area.value = data.replace(rNewline, '\\n');

                try {
                    this.form.submit();
                } catch (e) {}

                if (this.iframe.attachEvent) {
                    this.iframe.onreadystatechange = function () {
                        if (self.iframe.readyState === 'complete') {
                            complete();
                        }
                    };
                } else {
                    this.iframe.onload = complete;
                }
            };

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"./polling":23,"component-inherit":10}],22:[function(require,module,exports){
        (function (global){
            /**
             * Module requirements.
             */

            var XMLHttpRequest = require('xmlhttprequest-ssl');
            var Polling = require('./polling');
            var Emitter = require('component-emitter');
            var inherit = require('component-inherit');
            var debug = require('debug')('engine.io-client:polling-xhr');

            /**
             * Module exports.
             */

            module.exports = XHR;
            module.exports.Request = Request;

            /**
             * Empty function
             */

            function empty () {}

            /**
             * XHR Polling constructor.
             *
             * @param {Object} opts
             * @api public
             */

            function XHR (opts) {
                Polling.call(this, opts);
                this.requestTimeout = opts.requestTimeout;
                this.extraHeaders = opts.extraHeaders;

                if (global.location) {
                    var isSSL = 'https:' === location.protocol;
                    var port = location.port;

                    // some user agents have empty `location.port`
                    if (!port) {
                        port = isSSL ? 443 : 80;
                    }

                    this.xd = opts.hostname !== global.location.hostname ||
                        port !== opts.port;
                    this.xs = opts.secure !== isSSL;
                }
            }

            /**
             * Inherits from Polling.
             */

            inherit(XHR, Polling);

            /**
             * XHR supports binary
             */

            XHR.prototype.supportsBinary = true;

            /**
             * Creates a request.
             *
             * @param {String} method
             * @api private
             */

            XHR.prototype.request = function (opts) {
                opts = opts || {};
                opts.uri = this.uri();
                opts.xd = this.xd;
                opts.xs = this.xs;
                opts.agent = this.agent || false;
                opts.supportsBinary = this.supportsBinary;
                opts.enablesXDR = this.enablesXDR;

                // SSL options for Node.js client
                opts.pfx = this.pfx;
                opts.key = this.key;
                opts.passphrase = this.passphrase;
                opts.cert = this.cert;
                opts.ca = this.ca;
                opts.ciphers = this.ciphers;
                opts.rejectUnauthorized = this.rejectUnauthorized;
                opts.requestTimeout = this.requestTimeout;

                // other options for Node.js client
                opts.extraHeaders = this.extraHeaders;

                return new Request(opts);
            };

            /**
             * Sends data.
             *
             * @param {String} data to send.
             * @param {Function} called upon flush.
             * @api private
             */

            XHR.prototype.doWrite = function (data, fn) {
                var isBinary = typeof data !== 'string' && data !== undefined;
                var req = this.request({ method: 'POST', data: data, isBinary: isBinary });
                var self = this;
                req.on('success', fn);
                req.on('error', function (err) {
                    self.onError('xhr post error', err);
                });
                this.sendXhr = req;
            };

            /**
             * Starts a poll cycle.
             *
             * @api private
             */

            XHR.prototype.doPoll = function () {
                debug('xhr poll');
                var req = this.request();
                var self = this;
                req.on('data', function (data) {
                    self.onData(data);
                });
                req.on('error', function (err) {
                    self.onError('xhr poll error', err);
                });
                this.pollXhr = req;
            };

            /**
             * Request constructor
             *
             * @param {Object} options
             * @api public
             */

            function Request (opts) {
                this.method = opts.method || 'GET';
                this.uri = opts.uri;
                this.xd = !!opts.xd;
                this.xs = !!opts.xs;
                this.async = false !== opts.async;
                this.data = undefined !== opts.data ? opts.data : null;
                this.agent = opts.agent;
                this.isBinary = opts.isBinary;
                this.supportsBinary = opts.supportsBinary;
                this.enablesXDR = opts.enablesXDR;
                this.requestTimeout = opts.requestTimeout;

                // SSL options for Node.js client
                this.pfx = opts.pfx;
                this.key = opts.key;
                this.passphrase = opts.passphrase;
                this.cert = opts.cert;
                this.ca = opts.ca;
                this.ciphers = opts.ciphers;
                this.rejectUnauthorized = opts.rejectUnauthorized;

                // other options for Node.js client
                this.extraHeaders = opts.extraHeaders;

                this.create();
            }

            /**
             * Mix in `Emitter`.
             */

            Emitter(Request.prototype);

            /**
             * Creates the XHR object and sends the request.
             *
             * @api private
             */

            Request.prototype.create = function () {
                var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR };

                // SSL options for Node.js client
                opts.pfx = this.pfx;
                opts.key = this.key;
                opts.passphrase = this.passphrase;
                opts.cert = this.cert;
                opts.ca = this.ca;
                opts.ciphers = this.ciphers;
                opts.rejectUnauthorized = this.rejectUnauthorized;

                var xhr = this.xhr = new XMLHttpRequest(opts);
                var self = this;

                try {
                    debug('xhr open %s: %s', this.method, this.uri);
                    xhr.open(this.method, this.uri, this.async);
                    try {
                        if (this.extraHeaders) {
                            xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true);
                            for (var i in this.extraHeaders) {
                                if (this.extraHeaders.hasOwnProperty(i)) {
                                    xhr.setRequestHeader(i, this.extraHeaders[i]);
                                }
                            }
                        }
                    } catch (e) {}

                    if ('POST' === this.method) {
                        try {
                            if (this.isBinary) {
                                xhr.setRequestHeader('Content-type', 'application/octet-stream');
                            } else {
                                xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
                            }
                        } catch (e) {}
                    }

                    try {
                        xhr.setRequestHeader('Accept', '*/*');
                    } catch (e) {}

                    // ie6 check
                    if ('withCredentials' in xhr) {
                        xhr.withCredentials = true;
                    }

                    if (this.requestTimeout) {
                        xhr.timeout = this.requestTimeout;
                    }

                    if (this.hasXDR()) {
                        xhr.onload = function () {
                            self.onLoad();
                        };
                        xhr.onerror = function () {
                            self.onError(xhr.responseText);
                        };
                    } else {
                        xhr.onreadystatechange = function () {
                            if (xhr.readyState === 2) {
                                var contentType;
                                try {
                                    contentType = xhr.getResponseHeader('Content-Type');
                                } catch (e) {}
                                if (contentType === 'application/octet-stream') {
                                    xhr.responseType = 'arraybuffer';
                                }
                            }
                            if (4 !== xhr.readyState) return;
                            if (200 === xhr.status || 1223 === xhr.status) {
                                self.onLoad();
                            } else {
                                // make sure the `error` event handler that's user-set
                                // does not throw in the same tick and gets caught here
                                setTimeout(function () {
                                    self.onError(xhr.status);
                                }, 0);
                            }
                        };
                    }

                    debug('xhr data %s', this.data);
                    xhr.send(this.data);
                } catch (e) {
                    // Need to defer since .create() is called directly fhrom the constructor
                    // and thus the 'error' event can only be only bound *after* this exception
                    // occurs.  Therefore, also, we cannot throw here at all.
                    setTimeout(function () {
                        self.onError(e);
                    }, 0);
                    return;
                }

                if (global.document) {
                    this.index = Request.requestsCount++;
                    Request.requests[this.index] = this;
                }
            };

            /**
             * Called upon successful response.
             *
             * @api private
             */

            Request.prototype.onSuccess = function () {
                this.emit('success');
                this.cleanup();
            };

            /**
             * Called if we have data.
             *
             * @api private
             */

            Request.prototype.onData = function (data) {
                this.emit('data', data);
                this.onSuccess();
            };

            /**
             * Called upon error.
             *
             * @api private
             */

            Request.prototype.onError = function (err) {
                this.emit('error', err);
                this.cleanup(true);
            };

            /**
             * Cleans up house.
             *
             * @api private
             */

            Request.prototype.cleanup = function (fromError) {
                if ('undefined' === typeof this.xhr || null === this.xhr) {
                    return;
                }
                // xmlhttprequest
                if (this.hasXDR()) {
                    this.xhr.onload = this.xhr.onerror = empty;
                } else {
                    this.xhr.onreadystatechange = empty;
                }

                if (fromError) {
                    try {
                        this.xhr.abort();
                    } catch (e) {}
                }

                if (global.document) {
                    delete Request.requests[this.index];
                }

                this.xhr = null;
            };

            /**
             * Called upon load.
             *
             * @api private
             */

            Request.prototype.onLoad = function () {
                var data;
                try {
                    var contentType;
                    try {
                        contentType = this.xhr.getResponseHeader('Content-Type');
                    } catch (e) {}
                    if (contentType === 'application/octet-stream') {
                        data = this.xhr.response || this.xhr.responseText;
                    } else {
                        data = this.xhr.responseText;
                    }
                } catch (e) {
                    this.onError(e);
                }
                if (null != data) {
                    this.onData(data);
                }
            };

            /**
             * Check if it has XDomainRequest.
             *
             * @api private
             */

            Request.prototype.hasXDR = function () {
                return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR;
            };

            /**
             * Aborts the request.
             *
             * @api public
             */

            Request.prototype.abort = function () {
                this.cleanup();
            };

            /**
             * Aborts pending requests when unloading the window. This is needed to prevent
             * memory leaks (e.g. when using IE) and to ensure that no spurious error is
             * emitted.
             */

            Request.requestsCount = 0;
            Request.requests = {};

            if (global.document) {
                if (global.attachEvent) {
                    global.attachEvent('onunload', unloadHandler);
                } else if (global.addEventListener) {
                    global.addEventListener('beforeunload', unloadHandler, false);
                }
            }

            function unloadHandler () {
                for (var i in Request.requests) {
                    if (Request.requests.hasOwnProperty(i)) {
                        Request.requests[i].abort();
                    }
                }
            }

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"./polling":23,"component-emitter":9,"component-inherit":10,"debug":26,"xmlhttprequest-ssl":25}],23:[function(require,module,exports){
        /**
         * Module dependencies.
         */

        var Transport = require('../transport');
        var parseqs = require('parseqs');
        var parser = require('engine.io-parser');
        var inherit = require('component-inherit');
        var yeast = require('yeast');
        var debug = require('debug')('engine.io-client:polling');

        /**
         * Module exports.
         */

        module.exports = Polling;

        /**
         * Is XHR2 supported?
         */

        var hasXHR2 = (function () {
            var XMLHttpRequest = require('xmlhttprequest-ssl');
            var xhr = new XMLHttpRequest({ xdomain: false });
            return null != xhr.responseType;
        })();

        /**
         * Polling interface.
         *
         * @param {Object} opts
         * @api private
         */

        function Polling (opts) {
            var forceBase64 = (opts && opts.forceBase64);
            if (!hasXHR2 || forceBase64) {
                this.supportsBinary = false;
            }
            Transport.call(this, opts);
        }

        /**
         * Inherits from Transport.
         */

        inherit(Polling, Transport);

        /**
         * Transport name.
         */

        Polling.prototype.name = 'polling';

        /**
         * Opens the socket (triggers polling). We write a PING message to determine
         * when the transport is open.
         *
         * @api private
         */

        Polling.prototype.doOpen = function () {
            this.poll();
        };

        /**
         * Pauses polling.
         *
         * @param {Function} callback upon buffers are flushed and transport is paused
         * @api private
         */

        Polling.prototype.pause = function (onPause) {
            var self = this;

            this.readyState = 'pausing';

            function pause () {
                debug('paused');
                self.readyState = 'paused';
                onPause();
            }

            if (this.polling || !this.writable) {
                var total = 0;

                if (this.polling) {
                    debug('we are currently polling - waiting to pause');
                    total++;
                    this.once('pollComplete', function () {
                        debug('pre-pause polling complete');
                        --total || pause();
                    });
                }

                if (!this.writable) {
                    debug('we are currently writing - waiting to pause');
                    total++;
                    this.once('drain', function () {
                        debug('pre-pause writing complete');
                        --total || pause();
                    });
                }
            } else {
                pause();
            }
        };

        /**
         * Starts polling cycle.
         *
         * @api public
         */

        Polling.prototype.poll = function () {
            debug('polling');
            this.polling = true;
            this.doPoll();
            this.emit('poll');
        };

        /**
         * Overloads onData to detect payloads.
         *
         * @api private
         */

        Polling.prototype.onData = function (data) {
            var self = this;
            debug('polling got data %s', data);
            var callback = function (packet, index, total) {
                // if its the first message we consider the transport open
                if ('opening' === self.readyState) {
                    self.onOpen();
                }

                // if its a close packet, we close the ongoing requests
                if ('close' === packet.type) {
                    self.onClose();
                    return false;
                }

                // otherwise bypass onData and handle the message
                self.onPacket(packet);
            };

            // decode payload
            parser.decodePayload(data, this.socket.binaryType, callback);

            // if an event did not trigger closing
            if ('closed' !== this.readyState) {
                // if we got data we're not polling
                this.polling = false;
                this.emit('pollComplete');

                if ('open' === this.readyState) {
                    this.poll();
                } else {
                    debug('ignoring poll - transport state "%s"', this.readyState);
                }
            }
        };

        /**
         * For polling, send a close packet.
         *
         * @api private
         */

        Polling.prototype.doClose = function () {
            var self = this;

            function close () {
                debug('writing close packet');
                self.write([{ type: 'close' }]);
            }

            if ('open' === this.readyState) {
                debug('transport open - closing');
                close();
            } else {
                // in case we're trying to close while
                // handshaking is in progress (GH-164)
                debug('transport not open - deferring close');
                this.once('open', close);
            }
        };

        /**
         * Writes a packets payload.
         *
         * @param {Array} data packets
         * @param {Function} drain callback
         * @api private
         */

        Polling.prototype.write = function (packets) {
            var self = this;
            this.writable = false;
            var callbackfn = function () {
                self.writable = true;
                self.emit('drain');
            };

            parser.encodePayload(packets, this.supportsBinary, function (data) {
                self.doWrite(data, callbackfn);
            });
        };

        /**
         * Generates uri for connection.
         *
         * @api private
         */

        Polling.prototype.uri = function () {
            var query = this.query || {};
            var schema = this.secure ? 'https' : 'http';
            var port = '';

            // cache busting is forced
            if (false !== this.timestampRequests) {
                query[this.timestampParam] = yeast();
            }

            if (!this.supportsBinary && !query.sid) {
                query.b64 = 1;
            }

            query = parseqs.encode(query);

            // avoid port if default for schema
            if (this.port && (('https' === schema && Number(this.port) !== 443) ||
                    ('http' === schema && Number(this.port) !== 80))) {
                port = ':' + this.port;
            }

            // prepend ? to query
            if (query.length) {
                query = '?' + query;
            }

            var ipv6 = this.hostname.indexOf(':') !== -1;
            return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
        };

    },{"../transport":19,"component-inherit":10,"debug":26,"engine.io-parser":29,"parseqs":44,"xmlhttprequest-ssl":25,"yeast":72}],24:[function(require,module,exports){
        (function (global){
            /**
             * Module dependencies.
             */

            var Transport = require('../transport');
            var parser = require('engine.io-parser');
            var parseqs = require('parseqs');
            var inherit = require('component-inherit');
            var yeast = require('yeast');
            var debug = require('debug')('engine.io-client:websocket');
            var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
            var NodeWebSocket;
            if (typeof window === 'undefined') {
                try {
                    NodeWebSocket = require('ws');
                } catch (e) { }
            }

            /**
             * Get either the `WebSocket` or `MozWebSocket` globals
             * in the browser or try to resolve WebSocket-compatible
             * interface exposed by `ws` for Node-like environment.
             */

            var WebSocket = BrowserWebSocket;
            if (!WebSocket && typeof window === 'undefined') {
                WebSocket = NodeWebSocket;
            }

            /**
             * Module exports.
             */

            module.exports = WS;

            /**
             * WebSocket transport constructor.
             *
             * @api {Object} connection options
             * @api public
             */

            function WS (opts) {
                var forceBase64 = (opts && opts.forceBase64);
                if (forceBase64) {
                    this.supportsBinary = false;
                }
                this.perMessageDeflate = opts.perMessageDeflate;
                this.usingBrowserWebSocket = BrowserWebSocket && !opts.forceNode;
                this.protocols = opts.protocols;
                if (!this.usingBrowserWebSocket) {
                    WebSocket = NodeWebSocket;
                }
                Transport.call(this, opts);
            }

            /**
             * Inherits from Transport.
             */

            inherit(WS, Transport);

            /**
             * Transport name.
             *
             * @api public
             */

            WS.prototype.name = 'websocket';

            /*
 * WebSockets support binary
 */

            WS.prototype.supportsBinary = true;

            /**
             * Opens socket.
             *
             * @api private
             */

            WS.prototype.doOpen = function () {
                if (!this.check()) {
                    // let probe timeout
                    return;
                }

                var uri = this.uri();
                var protocols = this.protocols;
                var opts = {
                    agent: this.agent,
                    perMessageDeflate: this.perMessageDeflate
                };

                // SSL options for Node.js client
                opts.pfx = this.pfx;
                opts.key = this.key;
                opts.passphrase = this.passphrase;
                opts.cert = this.cert;
                opts.ca = this.ca;
                opts.ciphers = this.ciphers;
                opts.rejectUnauthorized = this.rejectUnauthorized;
                if (this.extraHeaders) {
                    opts.headers = this.extraHeaders;
                }
                if (this.localAddress) {
                    opts.localAddress = this.localAddress;
                }

                try {
                    this.ws = this.usingBrowserWebSocket ? (protocols ? new WebSocket(uri, protocols) : new WebSocket(uri)) : new WebSocket(uri, protocols, opts);
                } catch (err) {
                    return this.emit('error', err);
                }

                if (this.ws.binaryType === undefined) {
                    this.supportsBinary = false;
                }

                if (this.ws.supports && this.ws.supports.binary) {
                    this.supportsBinary = true;
                    this.ws.binaryType = 'nodebuffer';
                } else {
                    this.ws.binaryType = 'arraybuffer';
                }

                this.addEventListeners();
            };

            /**
             * Adds event listeners to the socket
             *
             * @api private
             */

            WS.prototype.addEventListeners = function () {
                var self = this;

                this.ws.onopen = function () {
                    self.onOpen();
                };
                this.ws.onclose = function () {
                    self.onClose();
                };
                this.ws.onmessage = function (ev) {
                    self.onData(ev.data);
                };
                this.ws.onerror = function (e) {
                    self.onError('websocket error', e);
                };
            };

            /**
             * Writes data to socket.
             *
             * @param {Array} array of packets.
             * @api private
             */

            WS.prototype.write = function (packets) {
                var self = this;
                this.writable = false;

                // encodePacket efficient as it uses WS framing
                // no need for encodePayload
                var total = packets.length;
                for (var i = 0, l = total; i < l; i++) {
                    (function (packet) {
                        parser.encodePacket(packet, self.supportsBinary, function (data) {
                            if (!self.usingBrowserWebSocket) {
                                // always create a new object (GH-437)
                                var opts = {};
                                if (packet.options) {
                                    opts.compress = packet.options.compress;
                                }

                                if (self.perMessageDeflate) {
                                    var len = 'string' === typeof data ? global.Buffer.byteLength(data) : data.length;
                                    if (len < self.perMessageDeflate.threshold) {
                                        opts.compress = false;
                                    }
                                }
                            }

                            // Sometimes the websocket has already been closed but the browser didn't
                            // have a chance of informing us about it yet, in that case send will
                            // throw an error
                            try {
                                if (self.usingBrowserWebSocket) {
                                    // TypeError is thrown when passing the second argument on Safari
                                    self.ws.send(data);
                                } else {
                                    self.ws.send(data, opts);
                                }
                            } catch (e) {
                                debug('websocket closed before onclose event');
                            }

                            --total || done();
                        });
                    })(packets[i]);
                }

                function done () {
                    self.emit('flush');

                    // fake drain
                    // defer to next tick to allow Socket to clear writeBuffer
                    setTimeout(function () {
                        self.writable = true;
                        self.emit('drain');
                    }, 0);
                }
            };

            /**
             * Called upon close
             *
             * @api private
             */

            WS.prototype.onClose = function () {
                Transport.prototype.onClose.call(this);
            };

            /**
             * Closes socket.
             *
             * @api private
             */

            WS.prototype.doClose = function () {
                if (typeof this.ws !== 'undefined') {
                    this.ws.close();
                }
            };

            /**
             * Generates uri for connection.
             *
             * @api private
             */

            WS.prototype.uri = function () {
                var query = this.query || {};
                var schema = this.secure ? 'wss' : 'ws';
                var port = '';

                // avoid port if default for schema
                if (this.port && (('wss' === schema && Number(this.port) !== 443) ||
                        ('ws' === schema && Number(this.port) !== 80))) {
                    port = ':' + this.port;
                }

                // append timestamp to URI
                if (this.timestampRequests) {
                    query[this.timestampParam] = yeast();
                }

                // communicate binary support capabilities
                if (!this.supportsBinary) {
                    query.b64 = 1;
                }

                query = parseqs.encode(query);

                // prepend ? to query
                if (query.length) {
                    query = '?' + query;
                }

                var ipv6 = this.hostname.indexOf(':') !== -1;
                return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
            };

            /**
             * Feature detection for WebSocket.
             *
             * @return {Boolean} whether this transport is available.
             * @api public
             */

            WS.prototype.check = function () {
                return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
            };

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"../transport":19,"component-inherit":10,"debug":26,"engine.io-parser":29,"parseqs":44,"ws":5,"yeast":72}],25:[function(require,module,exports){
        (function (global){
// browser shim for xmlhttprequest module

            var hasCORS = require('has-cors');

            module.exports = function (opts) {
                var xdomain = opts.xdomain;

                // scheme must be same when usign XDomainRequest
                // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
                var xscheme = opts.xscheme;

                // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.
                // https://github.com/Automattic/engine.io-client/pull/217
                var enablesXDR = opts.enablesXDR;

                // XMLHttpRequest can be disabled on IE
                try {
                    if ('undefined' !== typeof XMLHttpRequest && (!xdomain || hasCORS)) {
                        return new XMLHttpRequest();
                    }
                } catch (e) { }

                // Use XDomainRequest for IE8 if enablesXDR is true
                // because loading bar keeps flashing when using jsonp-polling
                // https://github.com/yujiosaka/socke.io-ie8-loading-example
                try {
                    if ('undefined' !== typeof XDomainRequest && !xscheme && enablesXDR) {
                        return new XDomainRequest();
                    }
                } catch (e) { }

                if (!xdomain) {
                    try {
                        return new global[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP');
                    } catch (e) { }
                }
            };

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"has-cors":37}],26:[function(require,module,exports){
        (function (process){
            /**
             * This is the web browser implementation of `debug()`.
             *
             * Expose `debug()` as the module.
             */

            exports = module.exports = require('./debug');
            exports.log = log;
            exports.formatArgs = formatArgs;
            exports.save = save;
            exports.load = load;
            exports.useColors = useColors;
            exports.storage = 'undefined' != typeof chrome
            && 'undefined' != typeof chrome.storage
                ? chrome.storage.local
                : localstorage();

            /**
             * Colors.
             */

            exports.colors = [
                'lightseagreen',
                'forestgreen',
                'goldenrod',
                'dodgerblue',
                'darkorchid',
                'crimson'
            ];

            /**
             * Currently only WebKit-based Web Inspectors, Firefox >= v31,
             * and the Firebug extension (any Firefox version) are known
             * to support "%c" CSS customizations.
             *
             * TODO: add a `localStorage` variable to explicitly enable/disable colors
             */

            function useColors() {
                // NB: In an Electron preload script, document will be defined but not fully
                // initialized. Since we know we're in Chrome, we'll just detect this case
                // explicitly
                if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
                    return true;
                }

                // is webkit? http://stackoverflow.com/a/16459606/376773
                // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
                return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
                    // is firebug? http://stackoverflow.com/a/398120/376773
                    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
                    // is firefox >= v31?
                    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
                    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
                    // double check webkit in userAgent just in case we are in a worker
                    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
            }

            /**
             * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
             */

            exports.formatters.j = function(v) {
                try {
                    return JSON.stringify(v);
                } catch (err) {
                    return '[UnexpectedJSONParseError]: ' + err.message;
                }
            };


            /**
             * Colorize log arguments if enabled.
             *
             * @api public
             */

            function formatArgs(args) {
                var useColors = this.useColors;

                args[0] = (useColors ? '%c' : '')
                    + this.namespace
                    + (useColors ? ' %c' : ' ')
                    + args[0]
                    + (useColors ? '%c ' : ' ')
                    + '+' + exports.humanize(this.diff);

                if (!useColors) return;

                var c = 'color: ' + this.color;
                args.splice(1, 0, c, 'color: inherit')

                // the final "%c" is somewhat tricky, because there could be other
                // arguments passed either before or after the %c, so we need to
                // figure out the correct index to insert the CSS into
                var index = 0;
                var lastC = 0;
                args[0].replace(/%[a-zA-Z%]/g, function(match) {
                    if ('%%' === match) return;
                    index++;
                    if ('%c' === match) {
                        // we only are interested in the *last* %c
                        // (the user may have provided their own)
                        lastC = index;
                    }
                });

                args.splice(lastC, 0, c);
            }

            /**
             * Invokes `console.log()` when available.
             * No-op when `console.log` is not a "function".
             *
             * @api public
             */

            function log() {
                // this hackery is required for IE8/9, where
                // the `console.log` function doesn't have 'apply'
                return 'object' === typeof console
                    && console.log
                    && Function.prototype.apply.call(console.log, console, arguments);
            }

            /**
             * Save `namespaces`.
             *
             * @param {String} namespaces
             * @api private
             */

            function save(namespaces) {
                try {
                    if (null == namespaces) {
                        exports.storage.removeItem('debug');
                    } else {
                        exports.storage.debug = namespaces;
                    }
                } catch(e) {}
            }

            /**
             * Load `namespaces`.
             *
             * @return {String} returns the previously persisted debug modes
             * @api private
             */

            function load() {
                var r;
                try {
                    r = exports.storage.debug;
                } catch(e) {}

                // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
                if (!r && typeof process !== 'undefined' && 'env' in process) {
                    r = process.env.DEBUG;
                }

                return r;
            }

            /**
             * Enable namespaces listed in `localStorage.debug` initially.
             */

            exports.enable(load());

            /**
             * Localstorage attempts to return the localstorage.
             *
             * This is necessary because safari throws
             * when a user disables cookies/localstorage
             * and you attempt to access it.
             *
             * @return {LocalStorage}
             * @api private
             */

            function localstorage() {
                try {
                    return window.localStorage;
                } catch (e) {}
            }

        }).call(this,require('_process'))

    },{"./debug":27,"_process":6}],27:[function(require,module,exports){
        arguments[4][15][0].apply(exports,arguments)
    },{"dup":15,"ms":28}],28:[function(require,module,exports){
        /**
         * Helpers.
         */

        var s = 1000;
        var m = s * 60;
        var h = m * 60;
        var d = h * 24;
        var y = d * 365.25;

        /**
         * Parse or format the given `val`.
         *
         * Options:
         *
         *  - `long` verbose formatting [false]
         *
         * @param {String|Number} val
         * @param {Object} [options]
         * @throws {Error} throw an error if val is not a non-empty string or a number
         * @return {String|Number}
         * @api public
         */

        module.exports = function(val, options) {
            options = options || {};
            var type = typeof val;
            if (type === 'string' && val.length > 0) {
                return parse(val);
            } else if (type === 'number' && isNaN(val) === false) {
                return options.long ? fmtLong(val) : fmtShort(val);
            }
            throw new Error(
                'val is not a non-empty string or a valid number. val=' +
                JSON.stringify(val)
            );
        };

        /**
         * Parse the given `str` and return milliseconds.
         *
         * @param {String} str
         * @return {Number}
         * @api private
         */

        function parse(str) {
            str = String(str);
            if (str.length > 100) {
                return;
            }
            var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
                str
            );
            if (!match) {
                return;
            }
            var n = parseFloat(match[1]);
            var type = (match[2] || 'ms').toLowerCase();
            switch (type) {
                case 'years':
                case 'year':
                case 'yrs':
                case 'yr':
                case 'y':
                    return n * y;
                case 'days':
                case 'day':
                case 'd':
                    return n * d;
                case 'hours':
                case 'hour':
                case 'hrs':
                case 'hr':
                case 'h':
                    return n * h;
                case 'minutes':
                case 'minute':
                case 'mins':
                case 'min':
                case 'm':
                    return n * m;
                case 'seconds':
                case 'second':
                case 'secs':
                case 'sec':
                case 's':
                    return n * s;
                case 'milliseconds':
                case 'millisecond':
                case 'msecs':
                case 'msec':
                case 'ms':
                    return n;
                default:
                    return undefined;
            }
        }

        /**
         * Short format for `ms`.
         *
         * @param {Number} ms
         * @return {String}
         * @api private
         */

        function fmtShort(ms) {
            if (ms >= d) {
                return Math.round(ms / d) + 'd';
            }
            if (ms >= h) {
                return Math.round(ms / h) + 'h';
            }
            if (ms >= m) {
                return Math.round(ms / m) + 'm';
            }
            if (ms >= s) {
                return Math.round(ms / s) + 's';
            }
            return ms + 'ms';
        }

        /**
         * Long format for `ms`.
         *
         * @param {Number} ms
         * @return {String}
         * @api private
         */

        function fmtLong(ms) {
            return plural(ms, d, 'day') ||
                plural(ms, h, 'hour') ||
                plural(ms, m, 'minute') ||
                plural(ms, s, 'second') ||
                ms + ' ms';
        }

        /**
         * Pluralization helper.
         */

        function plural(ms, n, name) {
            if (ms < n) {
                return;
            }
            if (ms < n * 1.5) {
                return Math.floor(ms / n) + ' ' + name;
            }
            return Math.ceil(ms / n) + ' ' + name + 's';
        }

    },{}],29:[function(require,module,exports){
        (function (global){
            /**
             * Module dependencies.
             */

            var keys = require('./keys');
            var hasBinary = require('has-binary2');
            var sliceBuffer = require('arraybuffer.slice');
            var after = require('after');
            var utf8 = require('./utf8');

            var base64encoder;
            if (global && global.ArrayBuffer) {
                base64encoder = require('base64-arraybuffer');
            }

            /**
             * Check if we are running an android browser. That requires us to use
             * ArrayBuffer with polling transports...
             *
             * http://ghinda.net/jpeg-blob-ajax-android/
             */

            var isAndroid = typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent);

            /**
             * Check if we are running in PhantomJS.
             * Uploading a Blob with PhantomJS does not work correctly, as reported here:
             * https://github.com/ariya/phantomjs/issues/11395
             * @type boolean
             */
            var isPhantomJS = typeof navigator !== 'undefined' && /PhantomJS/i.test(navigator.userAgent);

            /**
             * When true, avoids using Blobs to encode payloads.
             * @type boolean
             */
            var dontSendBlobs = isAndroid || isPhantomJS;

            /**
             * Current protocol version.
             */

            exports.protocol = 3;

            /**
             * Packet types.
             */

            var packets = exports.packets = {
                open:     0    // non-ws
                , close:    1    // non-ws
                , ping:     2
                , pong:     3
                , message:  4
                , upgrade:  5
                , noop:     6
            };

            var packetslist = keys(packets);

            /**
             * Premade error packet.
             */

            var err = { type: 'error', data: 'parser error' };

            /**
             * Create a blob api even for blob builder when vendor prefixes exist
             */

            var Blob = require('blob');

            /**
             * Encodes a packet.
             *
             *     <packet type id> [ <data> ]
             *
             * Example:
             *
             *     5hello world
             *     3
             *     4
             *
             * Binary is encoded in an identical principle
             *
             * @api private
             */

            exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
                if (typeof supportsBinary === 'function') {
                    callback = supportsBinary;
                    supportsBinary = false;
                }

                if (typeof utf8encode === 'function') {
                    callback = utf8encode;
                    utf8encode = null;
                }

                var data = (packet.data === undefined)
                    ? undefined
                    : packet.data.buffer || packet.data;

                if (global.ArrayBuffer && data instanceof ArrayBuffer) {
                    return encodeArrayBuffer(packet, supportsBinary, callback);
                } else if (Blob && data instanceof global.Blob) {
                    return encodeBlob(packet, supportsBinary, callback);
                }

                // might be an object with { base64: true, data: dataAsBase64String }
                if (data && data.base64) {
                    return encodeBase64Object(packet, callback);
                }

                // Sending data as a utf-8 string
                var encoded = packets[packet.type];

                // data fragment is optional
                if (undefined !== packet.data) {
                    encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data);
                }

                return callback('' + encoded);

            };

            function encodeBase64Object(packet, callback) {
                // packet data is an object { base64: true, data: dataAsBase64String }
                var message = 'b' + exports.packets[packet.type] + packet.data.data;
                return callback(message);
            }

            /**
             * Encode packet helpers for binary types
             */

            function encodeArrayBuffer(packet, supportsBinary, callback) {
                if (!supportsBinary) {
                    return exports.encodeBase64Packet(packet, callback);
                }

                var data = packet.data;
                var contentArray = new Uint8Array(data);
                var resultBuffer = new Uint8Array(1 + data.byteLength);

                resultBuffer[0] = packets[packet.type];
                for (var i = 0; i < contentArray.length; i++) {
                    resultBuffer[i+1] = contentArray[i];
                }

                return callback(resultBuffer.buffer);
            }

            function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) {
                if (!supportsBinary) {
                    return exports.encodeBase64Packet(packet, callback);
                }

                var fr = new FileReader();
                fr.onload = function() {
                    packet.data = fr.result;
                    exports.encodePacket(packet, supportsBinary, true, callback);
                };
                return fr.readAsArrayBuffer(packet.data);
            }

            function encodeBlob(packet, supportsBinary, callback) {
                if (!supportsBinary) {
                    return exports.encodeBase64Packet(packet, callback);
                }

                if (dontSendBlobs) {
                    return encodeBlobAsArrayBuffer(packet, supportsBinary, callback);
                }

                var length = new Uint8Array(1);
                length[0] = packets[packet.type];
                var blob = new Blob([length.buffer, packet.data]);

                return callback(blob);
            }

            /**
             * Encodes a packet with binary data in a base64 string
             *
             * @param {Object} packet, has `type` and `data`
             * @return {String} base64 encoded message
             */

            exports.encodeBase64Packet = function(packet, callback) {
                var message = 'b' + exports.packets[packet.type];
                if (Blob && packet.data instanceof global.Blob) {
                    var fr = new FileReader();
                    fr.onload = function() {
                        var b64 = fr.result.split(',')[1];
                        callback(message + b64);
                    };
                    return fr.readAsDataURL(packet.data);
                }

                var b64data;
                try {
                    b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data));
                } catch (e) {
                    // iPhone Safari doesn't let you apply with typed arrays
                    var typed = new Uint8Array(packet.data);
                    var basic = new Array(typed.length);
                    for (var i = 0; i < typed.length; i++) {
                        basic[i] = typed[i];
                    }
                    b64data = String.fromCharCode.apply(null, basic);
                }
                message += global.btoa(b64data);
                return callback(message);
            };

            /**
             * Decodes a packet. Changes format to Blob if requested.
             *
             * @return {Object} with `type` and `data` (if any)
             * @api private
             */

            exports.decodePacket = function (data, binaryType, utf8decode) {
                if (data === undefined) {
                    return err;
                }
                // String data
                if (typeof data === 'string') {
                    if (data.charAt(0) === 'b') {
                        return exports.decodeBase64Packet(data.substr(1), binaryType);
                    }

                    if (utf8decode) {
                        data = tryDecode(data);
                        if (data === false) {
                            return err;
                        }
                    }
                    var type = data.charAt(0);

                    if (Number(type) != type || !packetslist[type]) {
                        return err;
                    }

                    if (data.length > 1) {
                        return { type: packetslist[type], data: data.substring(1) };
                    } else {
                        return { type: packetslist[type] };
                    }
                }

                var asArray = new Uint8Array(data);
                var type = asArray[0];
                var rest = sliceBuffer(data, 1);
                if (Blob && binaryType === 'blob') {
                    rest = new Blob([rest]);
                }
                return { type: packetslist[type], data: rest };
            };

            function tryDecode(data) {
                try {
                    data = utf8.decode(data, { strict: false });
                } catch (e) {
                    return false;
                }
                return data;
            }

            /**
             * Decodes a packet encoded in a base64 string
             *
             * @param {String} base64 encoded message
             * @return {Object} with `type` and `data` (if any)
             */

            exports.decodeBase64Packet = function(msg, binaryType) {
                var type = packetslist[msg.charAt(0)];
                if (!base64encoder) {
                    return { type: type, data: { base64: true, data: msg.substr(1) } };
                }

                var data = base64encoder.decode(msg.substr(1));

                if (binaryType === 'blob' && Blob) {
                    data = new Blob([data]);
                }

                return { type: type, data: data };
            };

            /**
             * Encodes multiple messages (payload).
             *
             *     <length>:data
             *
             * Example:
             *
             *     11:hello world2:hi
             *
             * If any contents are binary, they will be encoded as base64 strings. Base64
             * encoded strings are marked with a b before the length specifier
             *
             * @param {Array} packets
             * @api private
             */

            exports.encodePayload = function (packets, supportsBinary, callback) {
                if (typeof supportsBinary === 'function') {
                    callback = supportsBinary;
                    supportsBinary = null;
                }

                var isBinary = hasBinary(packets);

                if (supportsBinary && isBinary) {
                    if (Blob && !dontSendBlobs) {
                        return exports.encodePayloadAsBlob(packets, callback);
                    }

                    return exports.encodePayloadAsArrayBuffer(packets, callback);
                }

                if (!packets.length) {
                    return callback('0:');
                }

                function setLengthHeader(message) {
                    return message.length + ':' + message;
                }

                function encodeOne(packet, doneCallback) {
                    exports.encodePacket(packet, !isBinary ? false : supportsBinary, false, function(message) {
                        doneCallback(null, setLengthHeader(message));
                    });
                }

                map(packets, encodeOne, function(err, results) {
                    return callback(results.join(''));
                });
            };

            /**
             * Async array map using after
             */

            function map(ary, each, done) {
                var result = new Array(ary.length);
                var next = after(ary.length, done);

                var eachWithIndex = function(i, el, cb) {
                    each(el, function(error, msg) {
                        result[i] = msg;
                        cb(error, result);
                    });
                };

                for (var i = 0; i < ary.length; i++) {
                    eachWithIndex(i, ary[i], next);
                }
            }

            /*
 * Decodes data when a payload is maybe expected. Possible binary contents are
 * decoded from their base64 representation
 *
 * @param {String} data, callback method
 * @api public
 */

            exports.decodePayload = function (data, binaryType, callback) {
                if (typeof data !== 'string') {
                    return exports.decodePayloadAsBinary(data, binaryType, callback);
                }

                if (typeof binaryType === 'function') {
                    callback = binaryType;
                    binaryType = null;
                }

                var packet;
                if (data === '') {
                    // parser error - ignoring payload
                    return callback(err, 0, 1);
                }

                var length = '', n, msg;

                for (var i = 0, l = data.length; i < l; i++) {
                    var chr = data.charAt(i);

                    if (chr !== ':') {
                        length += chr;
                        continue;
                    }

                    if (length === '' || (length != (n = Number(length)))) {
                        // parser error - ignoring payload
                        return callback(err, 0, 1);
                    }

                    msg = data.substr(i + 1, n);

                    if (length != msg.length) {
                        // parser error - ignoring payload
                        return callback(err, 0, 1);
                    }

                    if (msg.length) {
                        packet = exports.decodePacket(msg, binaryType, false);

                        if (err.type === packet.type && err.data === packet.data) {
                            // parser error in individual packet - ignoring payload
                            return callback(err, 0, 1);
                        }

                        var ret = callback(packet, i + n, l);
                        if (false === ret) return;
                    }

                    // advance cursor
                    i += n;
                    length = '';
                }

                if (length !== '') {
                    // parser error - ignoring payload
                    return callback(err, 0, 1);
                }

            };

            /**
             * Encodes multiple messages (payload) as binary.
             *
             * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
             * 255><data>
             *
             * Example:
             * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
             *
             * @param {Array} packets
             * @return {ArrayBuffer} encoded payload
             * @api private
             */

            exports.encodePayloadAsArrayBuffer = function(packets, callback) {
                if (!packets.length) {
                    return callback(new ArrayBuffer(0));
                }

                function encodeOne(packet, doneCallback) {
                    exports.encodePacket(packet, true, true, function(data) {
                        return doneCallback(null, data);
                    });
                }

                map(packets, encodeOne, function(err, encodedPackets) {
                    var totalLength = encodedPackets.reduce(function(acc, p) {
                        var len;
                        if (typeof p === 'string'){
                            len = p.length;
                        } else {
                            len = p.byteLength;
                        }
                        return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2
                    }, 0);

                    var resultArray = new Uint8Array(totalLength);

                    var bufferIndex = 0;
                    encodedPackets.forEach(function(p) {
                        var isString = typeof p === 'string';
                        var ab = p;
                        if (isString) {
                            var view = new Uint8Array(p.length);
                            for (var i = 0; i < p.length; i++) {
                                view[i] = p.charCodeAt(i);
                            }
                            ab = view.buffer;
                        }

                        if (isString) { // not true binary
                            resultArray[bufferIndex++] = 0;
                        } else { // true binary
                            resultArray[bufferIndex++] = 1;
                        }

                        var lenStr = ab.byteLength.toString();
                        for (var i = 0; i < lenStr.length; i++) {
                            resultArray[bufferIndex++] = parseInt(lenStr[i]);
                        }
                        resultArray[bufferIndex++] = 255;

                        var view = new Uint8Array(ab);
                        for (var i = 0; i < view.length; i++) {
                            resultArray[bufferIndex++] = view[i];
                        }
                    });

                    return callback(resultArray.buffer);
                });
            };

            /**
             * Encode as Blob
             */

            exports.encodePayloadAsBlob = function(packets, callback) {
                function encodeOne(packet, doneCallback) {
                    exports.encodePacket(packet, true, true, function(encoded) {
                        var binaryIdentifier = new Uint8Array(1);
                        binaryIdentifier[0] = 1;
                        if (typeof encoded === 'string') {
                            var view = new Uint8Array(encoded.length);
                            for (var i = 0; i < encoded.length; i++) {
                                view[i] = encoded.charCodeAt(i);
                            }
                            encoded = view.buffer;
                            binaryIdentifier[0] = 0;
                        }

                        var len = (encoded instanceof ArrayBuffer)
                            ? encoded.byteLength
                            : encoded.size;

                        var lenStr = len.toString();
                        var lengthAry = new Uint8Array(lenStr.length + 1);
                        for (var i = 0; i < lenStr.length; i++) {
                            lengthAry[i] = parseInt(lenStr[i]);
                        }
                        lengthAry[lenStr.length] = 255;

                        if (Blob) {
                            var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]);
                            doneCallback(null, blob);
                        }
                    });
                }

                map(packets, encodeOne, function(err, results) {
                    return callback(new Blob(results));
                });
            };

            /*
 * Decodes data when a payload is maybe expected. Strings are decoded by
 * interpreting each byte as a key code for entries marked to start with 0. See
 * description of encodePayloadAsBinary
 *
 * @param {ArrayBuffer} data, callback method
 * @api public
 */

            exports.decodePayloadAsBinary = function (data, binaryType, callback) {
                if (typeof binaryType === 'function') {
                    callback = binaryType;
                    binaryType = null;
                }

                var bufferTail = data;
                var buffers = [];

                while (bufferTail.byteLength > 0) {
                    var tailArray = new Uint8Array(bufferTail);
                    var isString = tailArray[0] === 0;
                    var msgLength = '';

                    for (var i = 1; ; i++) {
                        if (tailArray[i] === 255) break;

                        // 310 = char length of Number.MAX_VALUE
                        if (msgLength.length > 310) {
                            return callback(err, 0, 1);
                        }

                        msgLength += tailArray[i];
                    }

                    bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length);
                    msgLength = parseInt(msgLength);

                    var msg = sliceBuffer(bufferTail, 0, msgLength);
                    if (isString) {
                        try {
                            msg = String.fromCharCode.apply(null, new Uint8Array(msg));
                        } catch (e) {
                            // iPhone Safari doesn't let you apply to typed arrays
                            var typed = new Uint8Array(msg);
                            msg = '';
                            for (var i = 0; i < typed.length; i++) {
                                msg += String.fromCharCode(typed[i]);
                            }
                        }
                    }

                    buffers.push(msg);
                    bufferTail = sliceBuffer(bufferTail, msgLength);
                }

                var total = buffers.length;
                buffers.forEach(function(buffer, i) {
                    callback(exports.decodePacket(buffer, binaryType, true), i, total);
                });
            };

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"./keys":30,"./utf8":31,"after":1,"arraybuffer.slice":32,"base64-arraybuffer":3,"blob":4,"has-binary2":36}],30:[function(require,module,exports){

        /**
         * Gets the keys for an object.
         *
         * @return {Array} keys
         * @api private
         */

        module.exports = Object.keys || function keys (obj){
            var arr = [];
            var has = Object.prototype.hasOwnProperty;

            for (var i in obj) {
                if (has.call(obj, i)) {
                    arr.push(i);
                }
            }
            return arr;
        };

    },{}],31:[function(require,module,exports){
        (function (global){
            /*! https://mths.be/utf8js v2.1.2 by @mathias */
            ;(function(root) {

                // Detect free variables `exports`
                var freeExports = typeof exports == 'object' && exports;

                // Detect free variable `module`
                var freeModule = typeof module == 'object' && module &&
                    module.exports == freeExports && module;

                // Detect free variable `global`, from Node.js or Browserified code,
                // and use it as `root`
                var freeGlobal = typeof global == 'object' && global;
                if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
                    root = freeGlobal;
                }

                /*--------------------------------------------------------------------------*/

                var stringFromCharCode = String.fromCharCode;

                // Taken from https://mths.be/punycode
                function ucs2decode(string) {
                    var output = [];
                    var counter = 0;
                    var length = string.length;
                    var value;
                    var extra;
                    while (counter < length) {
                        value = string.charCodeAt(counter++);
                        if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
                            // high surrogate, and there is a next character
                            extra = string.charCodeAt(counter++);
                            if ((extra & 0xFC00) == 0xDC00) { // low surrogate
                                output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
                            } else {
                                // unmatched surrogate; only append this code unit, in case the next
                                // code unit is the high surrogate of a surrogate pair
                                output.push(value);
                                counter--;
                            }
                        } else {
                            output.push(value);
                        }
                    }
                    return output;
                }

                // Taken from https://mths.be/punycode
                function ucs2encode(array) {
                    var length = array.length;
                    var index = -1;
                    var value;
                    var output = '';
                    while (++index < length) {
                        value = array[index];
                        if (value > 0xFFFF) {
                            value -= 0x10000;
                            output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
                            value = 0xDC00 | value & 0x3FF;
                        }
                        output += stringFromCharCode(value);
                    }
                    return output;
                }

                function checkScalarValue(codePoint, strict) {
                    if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
                        if (strict) {
                            throw Error(
                                'Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
                                ' is not a scalar value'
                            );
                        }
                        return false;
                    }
                    return true;
                }
                /*--------------------------------------------------------------------------*/

                function createByte(codePoint, shift) {
                    return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
                }

                function encodeCodePoint(codePoint, strict) {
                    if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
                        return stringFromCharCode(codePoint);
                    }
                    var symbol = '';
                    if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
                        symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
                    }
                    else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
                        if (!checkScalarValue(codePoint, strict)) {
                            codePoint = 0xFFFD;
                        }
                        symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
                        symbol += createByte(codePoint, 6);
                    }
                    else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
                        symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
                        symbol += createByte(codePoint, 12);
                        symbol += createByte(codePoint, 6);
                    }
                    symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
                    return symbol;
                }

                function utf8encode(string, opts) {
                    opts = opts || {};
                    var strict = false !== opts.strict;

                    var codePoints = ucs2decode(string);
                    var length = codePoints.length;
                    var index = -1;
                    var codePoint;
                    var byteString = '';
                    while (++index < length) {
                        codePoint = codePoints[index];
                        byteString += encodeCodePoint(codePoint, strict);
                    }
                    return byteString;
                }

                /*--------------------------------------------------------------------------*/

                function readContinuationByte() {
                    if (byteIndex >= byteCount) {
                        throw Error('Invalid byte index');
                    }

                    var continuationByte = byteArray[byteIndex] & 0xFF;
                    byteIndex++;

                    if ((continuationByte & 0xC0) == 0x80) {
                        return continuationByte & 0x3F;
                    }

                    // If we end up here, itâ€™s not a continuation byte
                    throw Error('Invalid continuation byte');
                }

                function decodeSymbol(strict) {
                    var byte1;
                    var byte2;
                    var byte3;
                    var byte4;
                    var codePoint;

                    if (byteIndex > byteCount) {
                        throw Error('Invalid byte index');
                    }

                    if (byteIndex == byteCount) {
                        return false;
                    }

                    // Read first byte
                    byte1 = byteArray[byteIndex] & 0xFF;
                    byteIndex++;

                    // 1-byte sequence (no continuation bytes)
                    if ((byte1 & 0x80) == 0) {
                        return byte1;
                    }

                    // 2-byte sequence
                    if ((byte1 & 0xE0) == 0xC0) {
                        byte2 = readContinuationByte();
                        codePoint = ((byte1 & 0x1F) << 6) | byte2;
                        if (codePoint >= 0x80) {
                            return codePoint;
                        } else {
                            throw Error('Invalid continuation byte');
                        }
                    }

                    // 3-byte sequence (may include unpaired surrogates)
                    if ((byte1 & 0xF0) == 0xE0) {
                        byte2 = readContinuationByte();
                        byte3 = readContinuationByte();
                        codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
                        if (codePoint >= 0x0800) {
                            return checkScalarValue(codePoint, strict) ? codePoint : 0xFFFD;
                        } else {
                            throw Error('Invalid continuation byte');
                        }
                    }

                    // 4-byte sequence
                    if ((byte1 & 0xF8) == 0xF0) {
                        byte2 = readContinuationByte();
                        byte3 = readContinuationByte();
                        byte4 = readContinuationByte();
                        codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) |
                            (byte3 << 0x06) | byte4;
                        if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
                            return codePoint;
                        }
                    }

                    throw Error('Invalid UTF-8 detected');
                }

                var byteArray;
                var byteCount;
                var byteIndex;
                function utf8decode(byteString, opts) {
                    opts = opts || {};
                    var strict = false !== opts.strict;

                    byteArray = ucs2decode(byteString);
                    byteCount = byteArray.length;
                    byteIndex = 0;
                    var codePoints = [];
                    var tmp;
                    while ((tmp = decodeSymbol(strict)) !== false) {
                        codePoints.push(tmp);
                    }
                    return ucs2encode(codePoints);
                }

                /*--------------------------------------------------------------------------*/

                var utf8 = {
                    'version': '2.1.2',
                    'encode': utf8encode,
                    'decode': utf8decode
                };

                // Some AMD build optimizers, like r.js, check for specific condition patterns
                // like the following:
                if (
                    typeof define == 'function' &&
                    typeof define.amd == 'object' &&
                    define.amd
                ) {
                    define(function() {
                        return utf8;
                    });
                }	else if (freeExports && !freeExports.nodeType) {
                    if (freeModule) { // in Node.js or RingoJS v0.8.0+
                        freeModule.exports = utf8;
                    } else { // in Narwhal or RingoJS v0.7.0-
                        var object = {};
                        var hasOwnProperty = object.hasOwnProperty;
                        for (var key in utf8) {
                            hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
                        }
                    }
                } else { // in Rhino or a web browser
                    root.utf8 = utf8;
                }

            }(this));

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{}],32:[function(require,module,exports){
        /**
         * An abstraction for slicing an arraybuffer even when
         * ArrayBuffer.prototype.slice is not supported
         *
         * @api public
         */

        module.exports = function(arraybuffer, start, end) {
            var bytes = arraybuffer.byteLength;
            start = start || 0;
            end = end || bytes;

            if (arraybuffer.slice) { return arraybuffer.slice(start, end); }

            if (start < 0) { start += bytes; }
            if (end < 0) { end += bytes; }
            if (end > bytes) { end = bytes; }

            if (start >= bytes || start >= end || bytes === 0) {
                return new ArrayBuffer(0);
            }

            var abv = new Uint8Array(arraybuffer);
            var result = new Uint8Array(end - start);
            for (var i = start, ii = 0; i < end; i++, ii++) {
                result[ii] = abv[i];
            }
            return result.buffer;
        };

    },{}],33:[function(require,module,exports){
        (function (process,global){
            /*!
 * @overview es6-promise - a tiny implementation of Promises/A+.
 * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
 * @license   Licensed under MIT license
 *            See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
 * @version   v4.2.2+97478eb6
 */

            (function (global, factory) {
                typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
                    typeof define === 'function' && define.amd ? define(factory) :
                        (global.ES6Promise = factory());
            }(this, (function () { 'use strict';

                function objectOrFunction(x) {
                    var type = typeof x;
                    return x !== null && (type === 'object' || type === 'function');
                }

                function isFunction(x) {
                    return typeof x === 'function';
                }



                var _isArray = void 0;
                if (Array.isArray) {
                    _isArray = Array.isArray;
                } else {
                    _isArray = function (x) {
                        return Object.prototype.toString.call(x) === '[object Array]';
                    };
                }

                var isArray = _isArray;

                var len = 0;
                var vertxNext = void 0;
                var customSchedulerFn = void 0;

                var asap = function asap(callback, arg) {
                    queue[len] = callback;
                    queue[len + 1] = arg;
                    len += 2;
                    if (len === 2) {
                        // If len is 2, that means that we need to schedule an async flush.
                        // If additional callbacks are queued before the queue is flushed, they
                        // will be processed by this flush that we are scheduling.
                        if (customSchedulerFn) {
                            customSchedulerFn(flush);
                        } else {
                            scheduleFlush();
                        }
                    }
                };

                function setScheduler(scheduleFn) {
                    customSchedulerFn = scheduleFn;
                }

                function setAsap(asapFn) {
                    asap = asapFn;
                }

                var browserWindow = typeof window !== 'undefined' ? window : undefined;
                var browserGlobal = browserWindow || {};
                var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
                var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';

// test for web worker but not in IE10
                var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';

// node
                function useNextTick() {
                    // node version 0.10.x displays a deprecation warning when nextTick is used recursively
                    // see https://github.com/cujojs/when/issues/410 for details
                    return function () {
                        return process.nextTick(flush);
                    };
                }

// vertx
                function useVertxTimer() {
                    if (typeof vertxNext !== 'undefined') {
                        return function () {
                            vertxNext(flush);
                        };
                    }

                    return useSetTimeout();
                }

                function useMutationObserver() {
                    var iterations = 0;
                    var observer = new BrowserMutationObserver(flush);
                    var node = document.createTextNode('');
                    observer.observe(node, { characterData: true });

                    return function () {
                        node.data = iterations = ++iterations % 2;
                    };
                }

// web worker
                function useMessageChannel() {
                    var channel = new MessageChannel();
                    channel.port1.onmessage = flush;
                    return function () {
                        return channel.port2.postMessage(0);
                    };
                }

                function useSetTimeout() {
                    // Store setTimeout reference so es6-promise will be unaffected by
                    // other code modifying setTimeout (like sinon.useFakeTimers())
                    var globalSetTimeout = setTimeout;
                    return function () {
                        return globalSetTimeout(flush, 1);
                    };
                }

                var queue = new Array(1000);
                function flush() {
                    for (var i = 0; i < len; i += 2) {
                        var callback = queue[i];
                        var arg = queue[i + 1];

                        callback(arg);

                        queue[i] = undefined;
                        queue[i + 1] = undefined;
                    }

                    len = 0;
                }

                function attemptVertx() {
                    try {
                        var r = require;
                        var vertx = r('vertx');
                        vertxNext = vertx.runOnLoop || vertx.runOnContext;
                        return useVertxTimer();
                    } catch (e) {
                        return useSetTimeout();
                    }
                }

                var scheduleFlush = void 0;
// Decide what async method to use to triggering processing of queued callbacks:
                if (isNode) {
                    scheduleFlush = useNextTick();
                } else if (BrowserMutationObserver) {
                    scheduleFlush = useMutationObserver();
                } else if (isWorker) {
                    scheduleFlush = useMessageChannel();
                } else if (browserWindow === undefined && typeof require === 'function') {
                    scheduleFlush = attemptVertx();
                } else {
                    scheduleFlush = useSetTimeout();
                }

                function then(onFulfillment, onRejection) {
                    var parent = this;

                    var child = new this.constructor(noop);

                    if (child[PROMISE_ID] === undefined) {
                        makePromise(child);
                    }

                    var _state = parent._state;


                    if (_state) {
                        var callback = arguments[_state - 1];
                        asap(function () {
                            return invokeCallback(_state, child, callback, parent._result);
                        });
                    } else {
                        subscribe(parent, child, onFulfillment, onRejection);
                    }

                    return child;
                }

                /**
                 `Promise.resolve` returns a promise that will become resolved with the
                 passed `value`. It is shorthand for the following:

                 ```javascript
                 let promise = new Promise(function(resolve, reject){
    resolve(1);
  });

                 promise.then(function(value){
    // value === 1
  });
                 ```

                 Instead of writing the above, your code now simply becomes the following:

                 ```javascript
                 let promise = Promise.resolve(1);

                 promise.then(function(value){
    // value === 1
  });
                 ```

                 @method resolve
                 @static
                 @param {Any} value value that the returned promise will be resolved with
                 Useful for tooling.
                 @return {Promise} a promise that will become fulfilled with the given
                 `value`
                 */
                function resolve$1(object) {
                    /*jshint validthis:true */
                    var Constructor = this;

                    if (object && typeof object === 'object' && object.constructor === Constructor) {
                        return object;
                    }

                    var promise = new Constructor(noop);
                    resolve(promise, object);
                    return promise;
                }

                var PROMISE_ID = Math.random().toString(36).substring(16);

                function noop() {}

                var PENDING = void 0;
                var FULFILLED = 1;
                var REJECTED = 2;

                var GET_THEN_ERROR = new ErrorObject();

                function selfFulfillment() {
                    return new TypeError("You cannot resolve a promise with itself");
                }

                function cannotReturnOwn() {
                    return new TypeError('A promises callback cannot return that same promise.');
                }

                function getThen(promise) {
                    try {
                        return promise.then;
                    } catch (error) {
                        GET_THEN_ERROR.error = error;
                        return GET_THEN_ERROR;
                    }
                }

                function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {
                    try {
                        then$$1.call(value, fulfillmentHandler, rejectionHandler);
                    } catch (e) {
                        return e;
                    }
                }

                function handleForeignThenable(promise, thenable, then$$1) {
                    asap(function (promise) {
                        var sealed = false;
                        var error = tryThen(then$$1, thenable, function (value) {
                            if (sealed) {
                                return;
                            }
                            sealed = true;
                            if (thenable !== value) {
                                resolve(promise, value);
                            } else {
                                fulfill(promise, value);
                            }
                        }, function (reason) {
                            if (sealed) {
                                return;
                            }
                            sealed = true;

                            reject(promise, reason);
                        }, 'Settle: ' + (promise._label || ' unknown promise'));

                        if (!sealed && error) {
                            sealed = true;
                            reject(promise, error);
                        }
                    }, promise);
                }

                function handleOwnThenable(promise, thenable) {
                    if (thenable._state === FULFILLED) {
                        fulfill(promise, thenable._result);
                    } else if (thenable._state === REJECTED) {
                        reject(promise, thenable._result);
                    } else {
                        subscribe(thenable, undefined, function (value) {
                            return resolve(promise, value);
                        }, function (reason) {
                            return reject(promise, reason);
                        });
                    }
                }

                function handleMaybeThenable(promise, maybeThenable, then$$1) {
                    if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {
                        handleOwnThenable(promise, maybeThenable);
                    } else {
                        if (then$$1 === GET_THEN_ERROR) {
                            reject(promise, GET_THEN_ERROR.error);
                            GET_THEN_ERROR.error = null;
                        } else if (then$$1 === undefined) {
                            fulfill(promise, maybeThenable);
                        } else if (isFunction(then$$1)) {
                            handleForeignThenable(promise, maybeThenable, then$$1);
                        } else {
                            fulfill(promise, maybeThenable);
                        }
                    }
                }

                function resolve(promise, value) {
                    if (promise === value) {
                        reject(promise, selfFulfillment());
                    } else if (objectOrFunction(value)) {
                        handleMaybeThenable(promise, value, getThen(value));
                    } else {
                        fulfill(promise, value);
                    }
                }

                function publishRejection(promise) {
                    if (promise._onerror) {
                        promise._onerror(promise._result);
                    }

                    publish(promise);
                }

                function fulfill(promise, value) {
                    if (promise._state !== PENDING) {
                        return;
                    }

                    promise._result = value;
                    promise._state = FULFILLED;

                    if (promise._subscribers.length !== 0) {
                        asap(publish, promise);
                    }
                }

                function reject(promise, reason) {
                    if (promise._state !== PENDING) {
                        return;
                    }
                    promise._state = REJECTED;
                    promise._result = reason;

                    asap(publishRejection, promise);
                }

                function subscribe(parent, child, onFulfillment, onRejection) {
                    var _subscribers = parent._subscribers;
                    var length = _subscribers.length;


                    parent._onerror = null;

                    _subscribers[length] = child;
                    _subscribers[length + FULFILLED] = onFulfillment;
                    _subscribers[length + REJECTED] = onRejection;

                    if (length === 0 && parent._state) {
                        asap(publish, parent);
                    }
                }

                function publish(promise) {
                    var subscribers = promise._subscribers;
                    var settled = promise._state;

                    if (subscribers.length === 0) {
                        return;
                    }

                    var child = void 0,
                        callback = void 0,
                        detail = promise._result;

                    for (var i = 0; i < subscribers.length; i += 3) {
                        child = subscribers[i];
                        callback = subscribers[i + settled];

                        if (child) {
                            invokeCallback(settled, child, callback, detail);
                        } else {
                            callback(detail);
                        }
                    }

                    promise._subscribers.length = 0;
                }

                function ErrorObject() {
                    this.error = null;
                }

                var TRY_CATCH_ERROR = new ErrorObject();

                function tryCatch(callback, detail) {
                    try {
                        return callback(detail);
                    } catch (e) {
                        TRY_CATCH_ERROR.error = e;
                        return TRY_CATCH_ERROR;
                    }
                }

                function invokeCallback(settled, promise, callback, detail) {
                    var hasCallback = isFunction(callback),
                        value = void 0,
                        error = void 0,
                        succeeded = void 0,
                        failed = void 0;

                    if (hasCallback) {
                        value = tryCatch(callback, detail);

                        if (value === TRY_CATCH_ERROR) {
                            failed = true;
                            error = value.error;
                            value.error = null;
                        } else {
                            succeeded = true;
                        }

                        if (promise === value) {
                            reject(promise, cannotReturnOwn());
                            return;
                        }
                    } else {
                        value = detail;
                        succeeded = true;
                    }

                    if (promise._state !== PENDING) {
                        // noop
                    } else if (hasCallback && succeeded) {
                        resolve(promise, value);
                    } else if (failed) {
                        reject(promise, error);
                    } else if (settled === FULFILLED) {
                        fulfill(promise, value);
                    } else if (settled === REJECTED) {
                        reject(promise, value);
                    }
                }

                function initializePromise(promise, resolver) {
                    try {
                        resolver(function resolvePromise(value) {
                            resolve(promise, value);
                        }, function rejectPromise(reason) {
                            reject(promise, reason);
                        });
                    } catch (e) {
                        reject(promise, e);
                    }
                }

                var id = 0;
                function nextId() {
                    return id++;
                }

                function makePromise(promise) {
                    promise[PROMISE_ID] = id++;
                    promise._state = undefined;
                    promise._result = undefined;
                    promise._subscribers = [];
                }

                function validationError() {
                    return new Error('Array Methods must be provided an Array');
                }

                function validationError() {
                    return new Error('Array Methods must be provided an Array');
                }

                var Enumerator = function () {
                    function Enumerator(Constructor, input) {
                        this._instanceConstructor = Constructor;
                        this.promise = new Constructor(noop);

                        if (!this.promise[PROMISE_ID]) {
                            makePromise(this.promise);
                        }

                        if (isArray(input)) {
                            this.length = input.length;
                            this._remaining = input.length;

                            this._result = new Array(this.length);

                            if (this.length === 0) {
                                fulfill(this.promise, this._result);
                            } else {
                                this.length = this.length || 0;
                                this._enumerate(input);
                                if (this._remaining === 0) {
                                    fulfill(this.promise, this._result);
                                }
                            }
                        } else {
                            reject(this.promise, validationError());
                        }
                    }

                    Enumerator.prototype._enumerate = function _enumerate(input) {
                        for (var i = 0; this._state === PENDING && i < input.length; i++) {
                            this._eachEntry(input[i], i);
                        }
                    };

                    Enumerator.prototype._eachEntry = function _eachEntry(entry, i) {
                        var c = this._instanceConstructor;
                        var resolve$$1 = c.resolve;


                        if (resolve$$1 === resolve$1) {
                            var _then = getThen(entry);

                            if (_then === then && entry._state !== PENDING) {
                                this._settledAt(entry._state, i, entry._result);
                            } else if (typeof _then !== 'function') {
                                this._remaining--;
                                this._result[i] = entry;
                            } else if (c === Promise$1) {
                                var promise = new c(noop);
                                handleMaybeThenable(promise, entry, _then);
                                this._willSettleAt(promise, i);
                            } else {
                                this._willSettleAt(new c(function (resolve$$1) {
                                    return resolve$$1(entry);
                                }), i);
                            }
                        } else {
                            this._willSettleAt(resolve$$1(entry), i);
                        }
                    };

                    Enumerator.prototype._settledAt = function _settledAt(state, i, value) {
                        var promise = this.promise;


                        if (promise._state === PENDING) {
                            this._remaining--;

                            if (state === REJECTED) {
                                reject(promise, value);
                            } else {
                                this._result[i] = value;
                            }
                        }

                        if (this._remaining === 0) {
                            fulfill(promise, this._result);
                        }
                    };

                    Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) {
                        var enumerator = this;

                        subscribe(promise, undefined, function (value) {
                            return enumerator._settledAt(FULFILLED, i, value);
                        }, function (reason) {
                            return enumerator._settledAt(REJECTED, i, reason);
                        });
                    };

                    return Enumerator;
                }();

                /**
                 `Promise.all` accepts an array of promises, and returns a new promise which
                 is fulfilled with an array of fulfillment values for the passed promises, or
                 rejected with the reason of the first passed promise to be rejected. It casts all
                 elements of the passed iterable to promises as it runs this algorithm.

                 Example:

                 ```javascript
                 let promise1 = resolve(1);
                 let promise2 = resolve(2);
                 let promise3 = resolve(3);
                 let promises = [ promise1, promise2, promise3 ];

                 Promise.all(promises).then(function(array){
    // The array here would be [ 1, 2, 3 ];
  });
                 ```

                 If any of the `promises` given to `all` are rejected, the first promise
                 that is rejected will be given as an argument to the returned promises's
                 rejection handler. For example:

                 Example:

                 ```javascript
                 let promise1 = resolve(1);
                 let promise2 = reject(new Error("2"));
                 let promise3 = reject(new Error("3"));
                 let promises = [ promise1, promise2, promise3 ];

                 Promise.all(promises).then(function(array){
    // Code here never runs because there are rejected promises!
  }, function(error) {
    // error.message === "2"
  });
                 ```

                 @method all
                 @static
                 @param {Array} entries array of promises
                 @param {String} label optional string for labeling the promise.
                 Useful for tooling.
                 @return {Promise} promise that is fulfilled when all `promises` have been
                 fulfilled, or rejected if any of them become rejected.
                 @static
                 */
                function all(entries) {
                    return new Enumerator(this, entries).promise;
                }

                /**
                 `Promise.race` returns a new promise which is settled in the same way as the
                 first passed promise to settle.

                 Example:

                 ```javascript
                 let promise1 = new Promise(function(resolve, reject){
    setTimeout(function(){
      resolve('promise 1');
    }, 200);
  });

                 let promise2 = new Promise(function(resolve, reject){
    setTimeout(function(){
      resolve('promise 2');
    }, 100);
  });

                 Promise.race([promise1, promise2]).then(function(result){
    // result === 'promise 2' because it was resolved before promise1
    // was resolved.
  });
                 ```

                 `Promise.race` is deterministic in that only the state of the first
                 settled promise matters. For example, even if other promises given to the
                 `promises` array argument are resolved, but the first settled promise has
                 become rejected before the other promises became fulfilled, the returned
                 promise will become rejected:

                 ```javascript
                 let promise1 = new Promise(function(resolve, reject){
    setTimeout(function(){
      resolve('promise 1');
    }, 200);
  });

                 let promise2 = new Promise(function(resolve, reject){
    setTimeout(function(){
      reject(new Error('promise 2'));
    }, 100);
  });

                 Promise.race([promise1, promise2]).then(function(result){
    // Code here never runs
  }, function(reason){
    // reason.message === 'promise 2' because promise 2 became rejected before
    // promise 1 became fulfilled
  });
                 ```

                 An example real-world use case is implementing timeouts:

                 ```javascript
                 Promise.race([ajax('foo.json'), timeout(5000)])
                 ```

                 @method race
                 @static
                 @param {Array} promises array of promises to observe
                 Useful for tooling.
                 @return {Promise} a promise which settles in the same way as the first passed
                 promise to settle.
                 */
                function race(entries) {
                    /*jshint validthis:true */
                    var Constructor = this;

                    if (!isArray(entries)) {
                        return new Constructor(function (_, reject) {
                            return reject(new TypeError('You must pass an array to race.'));
                        });
                    } else {
                        return new Constructor(function (resolve, reject) {
                            var length = entries.length;
                            for (var i = 0; i < length; i++) {
                                Constructor.resolve(entries[i]).then(resolve, reject);
                            }
                        });
                    }
                }

                /**
                 `Promise.reject` returns a promise rejected with the passed `reason`.
                 It is shorthand for the following:

                 ```javascript
                 let promise = new Promise(function(resolve, reject){
    reject(new Error('WHOOPS'));
  });

                 promise.then(function(value){
    // Code here doesn't run because the promise is rejected!
  }, function(reason){
    // reason.message === 'WHOOPS'
  });
                 ```

                 Instead of writing the above, your code now simply becomes the following:

                 ```javascript
                 let promise = Promise.reject(new Error('WHOOPS'));

                 promise.then(function(value){
    // Code here doesn't run because the promise is rejected!
  }, function(reason){
    // reason.message === 'WHOOPS'
  });
                 ```

                 @method reject
                 @static
                 @param {Any} reason value that the returned promise will be rejected with.
                 Useful for tooling.
                 @return {Promise} a promise rejected with the given `reason`.
                 */
                function reject$1(reason) {
                    /*jshint validthis:true */
                    var Constructor = this;
                    var promise = new Constructor(noop);
                    reject(promise, reason);
                    return promise;
                }

                function needsResolver() {
                    throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
                }

                function needsNew() {
                    throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
                }

                /**
                 Promise objects represent the eventual result of an asynchronous operation. The
                 primary way of interacting with a promise is through its `then` method, which
                 registers callbacks to receive either a promise's eventual value or the reason
                 why the promise cannot be fulfilled.

                 Terminology
                 -----------

                 - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
                 - `thenable` is an object or function that defines a `then` method.
                 - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
                 - `exception` is a value that is thrown using the throw statement.
                 - `reason` is a value that indicates why a promise was rejected.
                 - `settled` the final resting state of a promise, fulfilled or rejected.

                 A promise can be in one of three states: pending, fulfilled, or rejected.

                 Promises that are fulfilled have a fulfillment value and are in the fulfilled
                 state.  Promises that are rejected have a rejection reason and are in the
                 rejected state.  A fulfillment value is never a thenable.

                 Promises can also be said to *resolve* a value.  If this value is also a
                 promise, then the original promise's settled state will match the value's
                 settled state.  So a promise that *resolves* a promise that rejects will
                 itself reject, and a promise that *resolves* a promise that fulfills will
                 itself fulfill.


                 Basic Usage:
                 ------------

                 ```js
                 let promise = new Promise(function(resolve, reject) {
    // on success
    resolve(value);

    // on failure
    reject(reason);
  });

                 promise.then(function(value) {
    // on fulfillment
  }, function(reason) {
    // on rejection
  });
                 ```

                 Advanced Usage:
                 ---------------

                 Promises shine when abstracting away asynchronous interactions such as
                 `XMLHttpRequest`s.

                 ```js
                 function getJSON(url) {
    return new Promise(function(resolve, reject){
      let xhr = new XMLHttpRequest();

      xhr.open('GET', url);
      xhr.onreadystatechange = handler;
      xhr.responseType = 'json';
      xhr.setRequestHeader('Accept', 'application/json');
      xhr.send();

      function handler() {
        if (this.readyState === this.DONE) {
          if (this.status === 200) {
            resolve(this.response);
          } else {
            reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
          }
        }
      };
    });
  }

                 getJSON('/posts.json').then(function(json) {
    // on fulfillment
  }, function(reason) {
    // on rejection
  });
                 ```

                 Unlike callbacks, promises are great composable primitives.

                 ```js
                 Promise.all([
                 getJSON('/posts'),
                 getJSON('/comments')
                 ]).then(function(values){
    values[0] // => postsJSON
    values[1] // => commentsJSON

    return values;
  });
                 ```

                 @class Promise
                 @param {Function} resolver
                 Useful for tooling.
                 @constructor
                 */

                var Promise$1 = function () {
                    function Promise(resolver) {
                        this[PROMISE_ID] = nextId();
                        this._result = this._state = undefined;
                        this._subscribers = [];

                        if (noop !== resolver) {
                            typeof resolver !== 'function' && needsResolver();
                            this instanceof Promise ? initializePromise(this, resolver) : needsNew();
                        }
                    }

                    /**
                     The primary way of interacting with a promise is through its `then` method,
                     which registers callbacks to receive either a promise's eventual value or the
                     reason why the promise cannot be fulfilled.
                     ```js
                     findUser().then(function(user){
    // user is available
  }, function(reason){
    // user is unavailable, and you are given the reason why
  });
                     ```
                     Chaining
                     --------
                     The return value of `then` is itself a promise.  This second, 'downstream'
                     promise is resolved with the return value of the first promise's fulfillment
                     or rejection handler, or rejected if the handler throws an exception.
                     ```js
                     findUser().then(function (user) {
    return user.name;
  }, function (reason) {
    return 'default name';
  }).then(function (userName) {
    // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
    // will be `'default name'`
  });
                     findUser().then(function (user) {
    throw new Error('Found user, but still unhappy');
  }, function (reason) {
    throw new Error('`findUser` rejected and we're unhappy');
  }).then(function (value) {
    // never reached
  }, function (reason) {
    // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
    // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
  });
                     ```
                     If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
                     ```js
                     findUser().then(function (user) {
    throw new PedagogicalException('Upstream error');
  }).then(function (value) {
    // never reached
  }).then(function (value) {
    // never reached
  }, function (reason) {
    // The `PedgagocialException` is propagated all the way down to here
  });
                     ```
                     Assimilation
                     ------------
                     Sometimes the value you want to propagate to a downstream promise can only be
                     retrieved asynchronously. This can be achieved by returning a promise in the
                     fulfillment or rejection handler. The downstream promise will then be pending
                     until the returned promise is settled. This is called *assimilation*.
                     ```js
                     findUser().then(function (user) {
    return findCommentsByAuthor(user);
  }).then(function (comments) {
    // The user's comments are now available
  });
                     ```
                     If the assimliated promise rejects, then the downstream promise will also reject.
                     ```js
                     findUser().then(function (user) {
    return findCommentsByAuthor(user);
  }).then(function (comments) {
    // If `findCommentsByAuthor` fulfills, we'll have the value here
  }, function (reason) {
    // If `findCommentsByAuthor` rejects, we'll have the reason here
  });
                     ```
                     Simple Example
                     --------------
                     Synchronous Example
                     ```javascript
                     let result;
                     try {
    result = findResult();
    // success
  } catch(reason) {
    // failure
  }
                     ```
                     Errback Example
                     ```js
                     findResult(function(result, err){
    if (err) {
      // failure
    } else {
      // success
    }
  });
                     ```
                     Promise Example;
                     ```javascript
                     findResult().then(function(result){
    // success
  }, function(reason){
    // failure
  });
                     ```
                     Advanced Example
                     --------------
                     Synchronous Example
                     ```javascript
                     let author, books;
                     try {
    author = findAuthor();
    books  = findBooksByAuthor(author);
    // success
  } catch(reason) {
    // failure
  }
                     ```
                     Errback Example
                     ```js
                     function foundBooks(books) {
   }
                     function failure(reason) {
   }
                     findAuthor(function(author, err){
    if (err) {
      failure(err);
      // failure
    } else {
      try {
        findBoooksByAuthor(author, function(books, err) {
          if (err) {
            failure(err);
          } else {
            try {
              foundBooks(books);
            } catch(reason) {
              failure(reason);
            }
          }
        });
      } catch(error) {
        failure(err);
      }
      // success
    }
  });
                     ```
                     Promise Example;
                     ```javascript
                     findAuthor().
                     then(findBooksByAuthor).
                     then(function(books){
      // found books
  }).catch(function(reason){
    // something went wrong
  });
                     ```
                     @method then
                     @param {Function} onFulfilled
                     @param {Function} onRejected
                     Useful for tooling.
                     @return {Promise}
                     */

                    /**
                     `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
                     as the catch block of a try/catch statement.
                     ```js
                     function findAuthor(){
  throw new Error('couldn't find that author');
  }
                     // synchronous
                     try {
  findAuthor();
  } catch(reason) {
  // something went wrong
  }
                     // async with promises
                     findAuthor().catch(function(reason){
  // something went wrong
  });
                     ```
                     @method catch
                     @param {Function} onRejection
                     Useful for tooling.
                     @return {Promise}
                     */


                    Promise.prototype.catch = function _catch(onRejection) {
                        return this.then(null, onRejection);
                    };

                    /**
                     `finally` will be invoked regardless of the promise's fate just as native
                     try/catch/finally behaves

                     Synchronous example:

                     ```js
                     findAuthor() {
      if (Math.random() > 0.5) {
        throw new Error();
      }
      return new Author();
    }

                     try {
      return findAuthor(); // succeed or fail
    } catch(error) {
      return findOtherAuther();
    } finally {
      // always runs
      // doesn't affect the return value
    }
                     ```

                     Asynchronous example:

                     ```js
                     findAuthor().catch(function(reason){
      return findOtherAuther();
    }).finally(function(){
      // author was either found, or not
    });
                     ```

                     @method finally
                     @param {Function} callback
                     @return {Promise}
                     */


                    Promise.prototype.finally = function _finally(callback) {
                        var promise = this;
                        var constructor = promise.constructor;

                        return promise.then(function (value) {
                            return constructor.resolve(callback()).then(function () {
                                return value;
                            });
                        }, function (reason) {
                            return constructor.resolve(callback()).then(function () {
                                throw reason;
                            });
                        });
                    };

                    return Promise;
                }();

                Promise$1.prototype.then = then;
                Promise$1.all = all;
                Promise$1.race = race;
                Promise$1.resolve = resolve$1;
                Promise$1.reject = reject$1;
                Promise$1._setScheduler = setScheduler;
                Promise$1._setAsap = setAsap;
                Promise$1._asap = asap;

                /*global self*/
                function polyfill() {
                    var local = void 0;

                    if (typeof global !== 'undefined') {
                        local = global;
                    } else if (typeof self !== 'undefined') {
                        local = self;
                    } else {
                        try {
                            local = Function('return this')();
                        } catch (e) {
                            throw new Error('polyfill failed because global object is unavailable in this environment');
                        }
                    }

                    var P = local.Promise;

                    if (P) {
                        var promiseToString = null;
                        try {
                            promiseToString = Object.prototype.toString.call(P.resolve());
                        } catch (e) {
                            // silently ignored
                        }

                        if (promiseToString === '[object Promise]' && !P.cast) {
                            return;
                        }
                    }

                    local.Promise = Promise$1;
                }

// Strange compat..
                Promise$1.polyfill = polyfill;
                Promise$1.Promise = Promise$1;

                return Promise$1;

            })));





        }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"_process":6}],34:[function(require,module,exports){
        'use strict';

        var hasOwn = Object.prototype.hasOwnProperty;
        var toStr = Object.prototype.toString;

        var isArray = function isArray(arr) {
            if (typeof Array.isArray === 'function') {
                return Array.isArray(arr);
            }

            return toStr.call(arr) === '[object Array]';
        };

        var isPlainObject = function isPlainObject(obj) {
            if (!obj || toStr.call(obj) !== '[object Object]') {
                return false;
            }

            var hasOwnConstructor = hasOwn.call(obj, 'constructor');
            var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
            // Not own constructor property must be Object
            if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
                return false;
            }

            // Own properties are enumerated firstly, so to speed up,
            // if last one is own, then all properties are own.
            var key;
            for (key in obj) { /**/ }

            return typeof key === 'undefined' || hasOwn.call(obj, key);
        };

        module.exports = function extend() {
            var options, name, src, copy, copyIsArray, clone;
            var target = arguments[0];
            var i = 1;
            var length = arguments.length;
            var deep = false;

            // Handle a deep copy situation
            if (typeof target === 'boolean') {
                deep = target;
                target = arguments[1] || {};
                // skip the boolean and the target
                i = 2;
            }
            if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {
                target = {};
            }

            for (; i < length; ++i) {
                options = arguments[i];
                // Only deal with non-null/undefined values
                if (options != null) {
                    // Extend the base object
                    for (name in options) {
                        src = target[name];
                        copy = options[name];

                        // Prevent never-ending loop
                        if (target !== copy) {
                            // Recurse if we're merging plain objects or arrays
                            if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
                                if (copyIsArray) {
                                    copyIsArray = false;
                                    clone = src && isArray(src) ? src : [];
                                } else {
                                    clone = src && isPlainObject(src) ? src : {};
                                }

                                // Never move original objects, clone them
                                target[name] = extend(deep, clone, copy);

                                // Don't bring in undefined values
                            } else if (typeof copy !== 'undefined') {
                                target[name] = copy;
                            }
                        }
                    }
                }
            }

            // Return the modified object
            return target;
        };

    },{}],35:[function(require,module,exports){
        module.exports = function flatten(list, depth) {
            depth = (typeof depth == 'number') ? depth : Infinity;

            if (!depth) {
                if (Array.isArray(list)) {
                    return list.map(function(i) { return i; });
                }
                return list;
            }

            return _flatten(list, 1);

            function _flatten(list, d) {
                return list.reduce(function (acc, item) {
                    if (Array.isArray(item) && d < depth) {
                        return acc.concat(_flatten(item, d + 1));
                    }
                    else {
                        return acc.concat(item);
                    }
                }, []);
            }
        };

    },{}],36:[function(require,module,exports){
        (function (global){
            /* global Blob File */

            /*
 * Module requirements.
 */

            var isArray = require('isarray');

            var toString = Object.prototype.toString;
            var withNativeBlob = typeof global.Blob === 'function' || toString.call(global.Blob) === '[object BlobConstructor]';
            var withNativeFile = typeof global.File === 'function' || toString.call(global.File) === '[object FileConstructor]';

            /**
             * Module exports.
             */

            module.exports = hasBinary;

            /**
             * Checks for binary data.
             *
             * Supports Buffer, ArrayBuffer, Blob and File.
             *
             * @param {Object} anything
             * @api public
             */

            function hasBinary (obj) {
                if (!obj || typeof obj !== 'object') {
                    return false;
                }

                if (isArray(obj)) {
                    for (var i = 0, l = obj.length; i < l; i++) {
                        if (hasBinary(obj[i])) {
                            return true;
                        }
                    }
                    return false;
                }

                if ((typeof global.Buffer === 'function' && global.Buffer.isBuffer && global.Buffer.isBuffer(obj)) ||
                    (typeof global.ArrayBuffer === 'function' && obj instanceof ArrayBuffer) ||
                    (withNativeBlob && obj instanceof Blob) ||
                    (withNativeFile && obj instanceof File)
                ) {
                    return true;
                }

                // see: https://github.com/Automattic/has-binary/pull/4
                if (obj.toJSON && typeof obj.toJSON === 'function' && arguments.length === 1) {
                    return hasBinary(obj.toJSON(), true);
                }

                for (var key in obj) {
                    if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) {
                        return true;
                    }
                }

                return false;
            }

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"isarray":39}],37:[function(require,module,exports){

        /**
         * Module exports.
         *
         * Logic borrowed from Modernizr:
         *
         *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
         */

        try {
            module.exports = typeof XMLHttpRequest !== 'undefined' &&
                'withCredentials' in new XMLHttpRequest();
        } catch (err) {
            // if XMLHttp support is disabled in IE then it will throw
            // when trying to create
            module.exports = false;
        }

    },{}],38:[function(require,module,exports){

        var indexOf = [].indexOf;

        module.exports = function(arr, obj){
            if (indexOf) return arr.indexOf(obj);
            for (var i = 0; i < arr.length; ++i) {
                if (arr[i] === obj) return i;
            }
            return -1;
        };
    },{}],39:[function(require,module,exports){
        var toString = {}.toString;

        module.exports = Array.isArray || function (arr) {
            return toString.call(arr) == '[object Array]';
        };

    },{}],40:[function(require,module,exports){
        (function (global){
            /**
             * lodash (Custom Build) <https://lodash.com/>
             * Build: `lodash modularize exports="npm" -o ./`
             * Copyright jQuery Foundation and other contributors <https://jquery.org/>
             * Released under MIT license <https://lodash.com/license>
             * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
             * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
             */

            /** Used as the `TypeError` message for "Functions" methods. */
            var FUNC_ERROR_TEXT = 'Expected a function';

            /** Used as references for various `Number` constants. */
            var NAN = 0 / 0;

            /** `Object#toString` result references. */
            var symbolTag = '[object Symbol]';

            /** Used to match leading and trailing whitespace. */
            var reTrim = /^\s+|\s+$/g;

            /** Used to detect bad signed hexadecimal string values. */
            var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;

            /** Used to detect binary string values. */
            var reIsBinary = /^0b[01]+$/i;

            /** Used to detect octal string values. */
            var reIsOctal = /^0o[0-7]+$/i;

            /** Built-in method references without a dependency on `root`. */
            var freeParseInt = parseInt;

            /** Detect free variable `global` from Node.js. */
            var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

            /** Detect free variable `self`. */
            var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

            /** Used as a reference to the global object. */
            var root = freeGlobal || freeSelf || Function('return this')();

            /** Used for built-in method references. */
            var objectProto = Object.prototype;

            /**
             * Used to resolve the
             * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
             * of values.
             */
            var objectToString = objectProto.toString;

            /* Built-in method references for those with the same name as other `lodash` methods. */
            var nativeMax = Math.max,
                nativeMin = Math.min;

            /**
             * Gets the timestamp of the number of milliseconds that have elapsed since
             * the Unix epoch (1 January 1970 00:00:00 UTC).
             *
             * @static
             * @memberOf _
             * @since 2.4.0
             * @category Date
             * @returns {number} Returns the timestamp.
             * @example
             *
             * _.defer(function(stamp) {
 *   console.log(_.now() - stamp);
 * }, _.now());
             * // => Logs the number of milliseconds it took for the deferred invocation.
             */
            var now = function() {
                return root.Date.now();
            };

            /**
             * Creates a debounced function that delays invoking `func` until after `wait`
             * milliseconds have elapsed since the last time the debounced function was
             * invoked. The debounced function comes with a `cancel` method to cancel
             * delayed `func` invocations and a `flush` method to immediately invoke them.
             * Provide `options` to indicate whether `func` should be invoked on the
             * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
             * with the last arguments provided to the debounced function. Subsequent
             * calls to the debounced function return the result of the last `func`
             * invocation.
             *
             * **Note:** If `leading` and `trailing` options are `true`, `func` is
             * invoked on the trailing edge of the timeout only if the debounced function
             * is invoked more than once during the `wait` timeout.
             *
             * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
             * until to the next tick, similar to `setTimeout` with a timeout of `0`.
             *
             * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
             * for details over the differences between `_.debounce` and `_.throttle`.
             *
             * @static
             * @memberOf _
             * @since 0.1.0
             * @category Function
             * @param {Function} func The function to debounce.
             * @param {number} [wait=0] The number of milliseconds to delay.
             * @param {Object} [options={}] The options object.
             * @param {boolean} [options.leading=false]
             *  Specify invoking on the leading edge of the timeout.
             * @param {number} [options.maxWait]
             *  The maximum time `func` is allowed to be delayed before it's invoked.
             * @param {boolean} [options.trailing=true]
             *  Specify invoking on the trailing edge of the timeout.
             * @returns {Function} Returns the new debounced function.
             * @example
             *
             * // Avoid costly calculations while the window size is in flux.
             * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
             *
             * // Invoke `sendMail` when clicked, debouncing subsequent calls.
             * jQuery(element).on('click', _.debounce(sendMail, 300, {
 *   'leading': true,
 *   'trailing': false
 * }));
             *
             * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
             * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
             * var source = new EventSource('/stream');
             * jQuery(source).on('message', debounced);
             *
             * // Cancel the trailing debounced invocation.
             * jQuery(window).on('popstate', debounced.cancel);
             */
            function debounce(func, wait, options) {
                var lastArgs,
                    lastThis,
                    maxWait,
                    result,
                    timerId,
                    lastCallTime,
                    lastInvokeTime = 0,
                    leading = false,
                    maxing = false,
                    trailing = true;

                if (typeof func != 'function') {
                    throw new TypeError(FUNC_ERROR_TEXT);
                }
                wait = toNumber(wait) || 0;
                if (isObject(options)) {
                    leading = !!options.leading;
                    maxing = 'maxWait' in options;
                    maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
                    trailing = 'trailing' in options ? !!options.trailing : trailing;
                }

                function invokeFunc(time) {
                    var args = lastArgs,
                        thisArg = lastThis;

                    lastArgs = lastThis = undefined;
                    lastInvokeTime = time;
                    result = func.apply(thisArg, args);
                    return result;
                }

                function leadingEdge(time) {
                    // Reset any `maxWait` timer.
                    lastInvokeTime = time;
                    // Start the timer for the trailing edge.
                    timerId = setTimeout(timerExpired, wait);
                    // Invoke the leading edge.
                    return leading ? invokeFunc(time) : result;
                }

                function remainingWait(time) {
                    var timeSinceLastCall = time - lastCallTime,
                        timeSinceLastInvoke = time - lastInvokeTime,
                        result = wait - timeSinceLastCall;

                    return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
                }

                function shouldInvoke(time) {
                    var timeSinceLastCall = time - lastCallTime,
                        timeSinceLastInvoke = time - lastInvokeTime;

                    // Either this is the first call, activity has stopped and we're at the
                    // trailing edge, the system time has gone backwards and we're treating
                    // it as the trailing edge, or we've hit the `maxWait` limit.
                    return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
                        (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
                }

                function timerExpired() {
                    var time = now();
                    if (shouldInvoke(time)) {
                        return trailingEdge(time);
                    }
                    // Restart the timer.
                    timerId = setTimeout(timerExpired, remainingWait(time));
                }

                function trailingEdge(time) {
                    timerId = undefined;

                    // Only invoke if we have `lastArgs` which means `func` has been
                    // debounced at least once.
                    if (trailing && lastArgs) {
                        return invokeFunc(time);
                    }
                    lastArgs = lastThis = undefined;
                    return result;
                }

                function cancel() {
                    if (timerId !== undefined) {
                        clearTimeout(timerId);
                    }
                    lastInvokeTime = 0;
                    lastArgs = lastCallTime = lastThis = timerId = undefined;
                }

                function flush() {
                    return timerId === undefined ? result : trailingEdge(now());
                }

                function debounced() {
                    var time = now(),
                        isInvoking = shouldInvoke(time);

                    lastArgs = arguments;
                    lastThis = this;
                    lastCallTime = time;

                    if (isInvoking) {
                        if (timerId === undefined) {
                            return leadingEdge(lastCallTime);
                        }
                        if (maxing) {
                            // Handle invocations in a tight loop.
                            timerId = setTimeout(timerExpired, wait);
                            return invokeFunc(lastCallTime);
                        }
                    }
                    if (timerId === undefined) {
                        timerId = setTimeout(timerExpired, wait);
                    }
                    return result;
                }
                debounced.cancel = cancel;
                debounced.flush = flush;
                return debounced;
            }

            /**
             * Creates a throttled function that only invokes `func` at most once per
             * every `wait` milliseconds. The throttled function comes with a `cancel`
             * method to cancel delayed `func` invocations and a `flush` method to
             * immediately invoke them. Provide `options` to indicate whether `func`
             * should be invoked on the leading and/or trailing edge of the `wait`
             * timeout. The `func` is invoked with the last arguments provided to the
             * throttled function. Subsequent calls to the throttled function return the
             * result of the last `func` invocation.
             *
             * **Note:** If `leading` and `trailing` options are `true`, `func` is
             * invoked on the trailing edge of the timeout only if the throttled function
             * is invoked more than once during the `wait` timeout.
             *
             * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
             * until to the next tick, similar to `setTimeout` with a timeout of `0`.
             *
             * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
             * for details over the differences between `_.throttle` and `_.debounce`.
             *
             * @static
             * @memberOf _
             * @since 0.1.0
             * @category Function
             * @param {Function} func The function to throttle.
             * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
             * @param {Object} [options={}] The options object.
             * @param {boolean} [options.leading=true]
             *  Specify invoking on the leading edge of the timeout.
             * @param {boolean} [options.trailing=true]
             *  Specify invoking on the trailing edge of the timeout.
             * @returns {Function} Returns the new throttled function.
             * @example
             *
             * // Avoid excessively updating the position while scrolling.
             * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
             *
             * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
             * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
             * jQuery(element).on('click', throttled);
             *
             * // Cancel the trailing throttled invocation.
             * jQuery(window).on('popstate', throttled.cancel);
             */
            function throttle(func, wait, options) {
                var leading = true,
                    trailing = true;

                if (typeof func != 'function') {
                    throw new TypeError(FUNC_ERROR_TEXT);
                }
                if (isObject(options)) {
                    leading = 'leading' in options ? !!options.leading : leading;
                    trailing = 'trailing' in options ? !!options.trailing : trailing;
                }
                return debounce(func, wait, {
                    'leading': leading,
                    'maxWait': wait,
                    'trailing': trailing
                });
            }

            /**
             * Checks if `value` is the
             * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
             * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
             *
             * @static
             * @memberOf _
             * @since 0.1.0
             * @category Lang
             * @param {*} value The value to check.
             * @returns {boolean} Returns `true` if `value` is an object, else `false`.
             * @example
             *
             * _.isObject({});
             * // => true
             *
             * _.isObject([1, 2, 3]);
             * // => true
             *
             * _.isObject(_.noop);
             * // => true
             *
             * _.isObject(null);
             * // => false
             */
            function isObject(value) {
                var type = typeof value;
                return !!value && (type == 'object' || type == 'function');
            }

            /**
             * Checks if `value` is object-like. A value is object-like if it's not `null`
             * and has a `typeof` result of "object".
             *
             * @static
             * @memberOf _
             * @since 4.0.0
             * @category Lang
             * @param {*} value The value to check.
             * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
             * @example
             *
             * _.isObjectLike({});
             * // => true
             *
             * _.isObjectLike([1, 2, 3]);
             * // => true
             *
             * _.isObjectLike(_.noop);
             * // => false
             *
             * _.isObjectLike(null);
             * // => false
             */
            function isObjectLike(value) {
                return !!value && typeof value == 'object';
            }

            /**
             * Checks if `value` is classified as a `Symbol` primitive or object.
             *
             * @static
             * @memberOf _
             * @since 4.0.0
             * @category Lang
             * @param {*} value The value to check.
             * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
             * @example
             *
             * _.isSymbol(Symbol.iterator);
             * // => true
             *
             * _.isSymbol('abc');
             * // => false
             */
            function isSymbol(value) {
                return typeof value == 'symbol' ||
                    (isObjectLike(value) && objectToString.call(value) == symbolTag);
            }

            /**
             * Converts `value` to a number.
             *
             * @static
             * @memberOf _
             * @since 4.0.0
             * @category Lang
             * @param {*} value The value to process.
             * @returns {number} Returns the number.
             * @example
             *
             * _.toNumber(3.2);
             * // => 3.2
             *
             * _.toNumber(Number.MIN_VALUE);
             * // => 5e-324
             *
             * _.toNumber(Infinity);
             * // => Infinity
             *
             * _.toNumber('3.2');
             * // => 3.2
             */
            function toNumber(value) {
                if (typeof value == 'number') {
                    return value;
                }
                if (isSymbol(value)) {
                    return NAN;
                }
                if (isObject(value)) {
                    var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
                    value = isObject(other) ? (other + '') : other;
                }
                if (typeof value != 'string') {
                    return value === 0 ? value : +value;
                }
                value = value.replace(reTrim, '');
                var isBinary = reIsBinary.test(value);
                return (isBinary || reIsOctal.test(value))
                    ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
                    : (reIsBadHex.test(value) ? NAN : +value);
            }

            module.exports = throttle;

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{}],41:[function(require,module,exports){
        var wildcard = require('wildcard');
        var reMimePartSplit = /[\/\+\.]/;

        /**
         # mime-match

         A simple function to checker whether a target mime type matches a mime-type
         pattern (e.g. image/jpeg matches image/jpeg OR image/*).

         ## Example Usage

         <<< example.js

         **/
        module.exports = function(target, pattern) {
            function test(pattern) {
                var result = wildcard(pattern, target, reMimePartSplit);

                // ensure that we have a valid mime type (should have two parts)
                return result && result.length >= 2;
            }

            return pattern ? test(pattern.split(';')[0]) : test;
        };

    },{"wildcard":71}],42:[function(require,module,exports){
        /**
         * Helpers.
         */

        var s = 1000
        var m = s * 60
        var h = m * 60
        var d = h * 24
        var y = d * 365.25

        /**
         * Parse or format the given `val`.
         *
         * Options:
         *
         *  - `long` verbose formatting [false]
         *
         * @param {String|Number} val
         * @param {Object} [options]
         * @throws {Error} throw an error if val is not a non-empty string or a number
         * @return {String|Number}
         * @api public
         */

        module.exports = function (val, options) {
            options = options || {}
            var type = typeof val
            if (type === 'string' && val.length > 0) {
                return parse(val)
            } else if (type === 'number' && isNaN(val) === false) {
                return options.long ?
                    fmtLong(val) :
                    fmtShort(val)
            }
            throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val))
        }

        /**
         * Parse the given `str` and return milliseconds.
         *
         * @param {String} str
         * @return {Number}
         * @api private
         */

        function parse(str) {
            str = String(str)
            if (str.length > 10000) {
                return
            }
            var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str)
            if (!match) {
                return
            }
            var n = parseFloat(match[1])
            var type = (match[2] || 'ms').toLowerCase()
            switch (type) {
                case 'years':
                case 'year':
                case 'yrs':
                case 'yr':
                case 'y':
                    return n * y
                case 'days':
                case 'day':
                case 'd':
                    return n * d
                case 'hours':
                case 'hour':
                case 'hrs':
                case 'hr':
                case 'h':
                    return n * h
                case 'minutes':
                case 'minute':
                case 'mins':
                case 'min':
                case 'm':
                    return n * m
                case 'seconds':
                case 'second':
                case 'secs':
                case 'sec':
                case 's':
                    return n * s
                case 'milliseconds':
                case 'millisecond':
                case 'msecs':
                case 'msec':
                case 'ms':
                    return n
                default:
                    return undefined
            }
        }

        /**
         * Short format for `ms`.
         *
         * @param {Number} ms
         * @return {String}
         * @api private
         */

        function fmtShort(ms) {
            if (ms >= d) {
                return Math.round(ms / d) + 'd'
            }
            if (ms >= h) {
                return Math.round(ms / h) + 'h'
            }
            if (ms >= m) {
                return Math.round(ms / m) + 'm'
            }
            if (ms >= s) {
                return Math.round(ms / s) + 's'
            }
            return ms + 'ms'
        }

        /**
         * Long format for `ms`.
         *
         * @param {Number} ms
         * @return {String}
         * @api private
         */

        function fmtLong(ms) {
            return plural(ms, d, 'day') ||
                plural(ms, h, 'hour') ||
                plural(ms, m, 'minute') ||
                plural(ms, s, 'second') ||
                ms + ' ms'
        }

        /**
         * Pluralization helper.
         */

        function plural(ms, n, name) {
            if (ms < n) {
                return
            }
            if (ms < n * 1.5) {
                return Math.floor(ms / n) + ' ' + name
            }
            return Math.ceil(ms / n) + ' ' + name + 's'
        }

    },{}],43:[function(require,module,exports){
        /**
         * Create an event emitter with namespaces
         * @name createNamespaceEmitter
         * @example
         * var emitter = require('./index')()
         *
         * emitter.on('*', function () {
*   console.log('all events emitted', this.event)
* })
         *
         * emitter.on('example', function () {
*   console.log('example event emitted')
* })
         */
        module.exports = function createNamespaceEmitter () {
            var emitter = {}
            var _fns = emitter._fns = {}

            /**
             * Emit an event. Optionally namespace the event. Handlers are fired in the order in which they were added with exact matches taking precedence. Separate the namespace and event with a `:`
             * @name emit
             * @param {String} event â€“ the name of the event, with optional namespace
             * @param {...*} data â€“ up to 6 arguments that are passed to the event listener
             * @example
             * emitter.emit('example')
             * emitter.emit('demo:test')
             * emitter.emit('data', { example: true}, 'a string', 1)
             */
            emitter.emit = function emit (event, arg1, arg2, arg3, arg4, arg5, arg6) {
                var toEmit = getListeners(event)

                if (toEmit.length) {
                    emitAll(event, toEmit, [arg1, arg2, arg3, arg4, arg5, arg6])
                }
            }

            /**
             * Create en event listener.
             * @name on
             * @param {String} event
             * @param {Function} fn
             * @example
             * emitter.on('example', function () {})
             * emitter.on('demo', function () {})
             */
            emitter.on = function on (event, fn) {
                if (!_fns[event]) {
                    _fns[event] = []
                }

                _fns[event].push(fn)
            }

            /**
             * Create en event listener that fires once.
             * @name once
             * @param {String} event
             * @param {Function} fn
             * @example
             * emitter.once('example', function () {})
             * emitter.once('demo', function () {})
             */
            emitter.once = function once (event, fn) {
                function one () {
                    fn.apply(this, arguments)
                    emitter.off(event, one)
                }
                this.on(event, one)
            }

            /**
             * Stop listening to an event. Stop all listeners on an event by only passing the event name. Stop a single listener by passing that event handler as a callback.
             * You must be explicit about what will be unsubscribed: `emitter.off('demo')` will unsubscribe an `emitter.on('demo')` listener,
             * `emitter.off('demo:example')` will unsubscribe an `emitter.on('demo:example')` listener
             * @name off
             * @param {String} event
             * @param {Function} [fn] â€“ the specific handler
             * @example
             * emitter.off('example')
             * emitter.off('demo', function () {})
             */
            emitter.off = function off (event, fn) {
                var keep = []

                if (event && fn) {
                    var fns = this._fns[event]
                    var i = 0
                    var l = fns.length

                    for (i; i < l; i++) {
                        if (fns[i] !== fn) {
                            keep.push(fns[i])
                        }
                    }
                }

                keep.length ? this._fns[event] = keep : delete this._fns[event]
            }

            function getListeners (e) {
                var out = _fns[e] ? _fns[e] : []
                var idx = e.indexOf(':')
                var args = (idx === -1) ? [e] : [e.substring(0, idx), e.substring(idx + 1)]

                var keys = Object.keys(_fns)
                var i = 0
                var l = keys.length

                for (i; i < l; i++) {
                    var key = keys[i]
                    if (key === '*') {
                        out = out.concat(_fns[key])
                    }

                    if (args.length === 2 && args[0] === key) {
                        out = out.concat(_fns[key])
                        break
                    }
                }

                return out
            }

            function emitAll (e, fns, args) {
                var i = 0
                var l = fns.length

                for (i; i < l; i++) {
                    if (!fns[i]) break
                    fns[i].event = e
                    fns[i].apply(fns[i], args)
                }
            }

            return emitter
        }

    },{}],44:[function(require,module,exports){
        /**
         * Compiles a querystring
         * Returns string representation of the object
         *
         * @param {Object}
         * @api private
         */

        exports.encode = function (obj) {
            var str = '';

            for (var i in obj) {
                if (obj.hasOwnProperty(i)) {
                    if (str.length) str += '&';
                    str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
                }
            }

            return str;
        };

        /**
         * Parses a simple querystring into an object
         *
         * @param {String} qs
         * @api private
         */

        exports.decode = function(qs){
            var qry = {};
            var pairs = qs.split('&');
            for (var i = 0, l = pairs.length; i < l; i++) {
                var pair = pairs[i].split('=');
                qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
            }
            return qry;
        };

    },{}],45:[function(require,module,exports){
        /**
         * Parses an URI
         *
         * @author Steven Levithan <stevenlevithan.com> (MIT license)
         * @api private
         */

        var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;

        var parts = [
            'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
        ];

        module.exports = function parseuri(str) {
            var src = str,
                b = str.indexOf('['),
                e = str.indexOf(']');

            if (b != -1 && e != -1) {
                str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
            }

            var m = re.exec(str || ''),
                uri = {},
                i = 14;

            while (i--) {
                uri[parts[i]] = m[i] || '';
            }

            if (b != -1 && e != -1) {
                uri.source = src;
                uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
                uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
                uri.ipv6uri = true;
            }

            return uri;
        };

    },{}],46:[function(require,module,exports){
        !function() {
            'use strict';
            function VNode() {}
            function h(nodeName, attributes) {
                var lastSimple, child, simple, i, children = EMPTY_CHILDREN;
                for (i = arguments.length; i-- > 2; ) stack.push(arguments[i]);
                if (attributes && null != attributes.children) {
                    if (!stack.length) stack.push(attributes.children);
                    delete attributes.children;
                }
                while (stack.length) if ((child = stack.pop()) && void 0 !== child.pop) for (i = child.length; i--; ) stack.push(child[i]); else {
                    if ('boolean' == typeof child) child = null;
                    if (simple = 'function' != typeof nodeName) if (null == child) child = ''; else if ('number' == typeof child) child = String(child); else if ('string' != typeof child) simple = !1;
                    if (simple && lastSimple) children[children.length - 1] += child; else if (children === EMPTY_CHILDREN) children = [ child ]; else children.push(child);
                    lastSimple = simple;
                }
                var p = new VNode();
                p.nodeName = nodeName;
                p.children = children;
                p.attributes = null == attributes ? void 0 : attributes;
                p.key = null == attributes ? void 0 : attributes.key;
                if (void 0 !== options.vnode) options.vnode(p);
                return p;
            }
            function extend(obj, props) {
                for (var i in props) obj[i] = props[i];
                return obj;
            }
            function cloneElement(vnode, props) {
                return h(vnode.nodeName, extend(extend({}, vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children);
            }
            function enqueueRender(component) {
                if (!component.__d && (component.__d = !0) && 1 == items.push(component)) (options.debounceRendering || defer)(rerender);
            }
            function rerender() {
                var p, list = items;
                items = [];
                while (p = list.pop()) if (p.__d) renderComponent(p);
            }
            function isSameNodeType(node, vnode, hydrating) {
                if ('string' == typeof vnode || 'number' == typeof vnode) return void 0 !== node.splitText;
                if ('string' == typeof vnode.nodeName) return !node._componentConstructor && isNamedNode(node, vnode.nodeName); else return hydrating || node._componentConstructor === vnode.nodeName;
            }
            function isNamedNode(node, nodeName) {
                return node.__n === nodeName || node.nodeName.toLowerCase() === nodeName.toLowerCase();
            }
            function getNodeProps(vnode) {
                var props = extend({}, vnode.attributes);
                props.children = vnode.children;
                var defaultProps = vnode.nodeName.defaultProps;
                if (void 0 !== defaultProps) for (var i in defaultProps) if (void 0 === props[i]) props[i] = defaultProps[i];
                return props;
            }
            function createNode(nodeName, isSvg) {
                var node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName);
                node.__n = nodeName;
                return node;
            }
            function removeNode(node) {
                var parentNode = node.parentNode;
                if (parentNode) parentNode.removeChild(node);
            }
            function setAccessor(node, name, old, value, isSvg) {
                if ('className' === name) name = 'class';
                if ('key' === name) ; else if ('ref' === name) {
                    if (old) old(null);
                    if (value) value(node);
                } else if ('class' === name && !isSvg) node.className = value || ''; else if ('style' === name) {
                    if (!value || 'string' == typeof value || 'string' == typeof old) node.style.cssText = value || '';
                    if (value && 'object' == typeof value) {
                        if ('string' != typeof old) for (var i in old) if (!(i in value)) node.style[i] = '';
                        for (var i in value) node.style[i] = 'number' == typeof value[i] && !1 === IS_NON_DIMENSIONAL.test(i) ? value[i] + 'px' : value[i];
                    }
                } else if ('dangerouslySetInnerHTML' === name) {
                    if (value) node.innerHTML = value.__html || '';
                } else if ('o' == name[0] && 'n' == name[1]) {
                    var useCapture = name !== (name = name.replace(/Capture$/, ''));
                    name = name.toLowerCase().substring(2);
                    if (value) {
                        if (!old) node.addEventListener(name, eventProxy, useCapture);
                    } else node.removeEventListener(name, eventProxy, useCapture);
                    (node.__l || (node.__l = {}))[name] = value;
                } else if ('list' !== name && 'type' !== name && !isSvg && name in node) {
                    setProperty(node, name, null == value ? '' : value);
                    if (null == value || !1 === value) node.removeAttribute(name);
                } else {
                    var ns = isSvg && name !== (name = name.replace(/^xlink\:?/, ''));
                    if (null == value || !1 === value) if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase()); else node.removeAttribute(name); else if ('function' != typeof value) if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value); else node.setAttribute(name, value);
                }
            }
            function setProperty(node, name, value) {
                try {
                    node[name] = value;
                } catch (e) {}
            }
            function eventProxy(e) {
                return this.__l[e.type](options.event && options.event(e) || e);
            }
            function flushMounts() {
                var c;
                while (c = mounts.pop()) {
                    if (options.afterMount) options.afterMount(c);
                    if (c.componentDidMount) c.componentDidMount();
                }
            }
            function diff(dom, vnode, context, mountAll, parent, componentRoot) {
                if (!diffLevel++) {
                    isSvgMode = null != parent && void 0 !== parent.ownerSVGElement;
                    hydrating = null != dom && !('__preactattr_' in dom);
                }
                var ret = idiff(dom, vnode, context, mountAll, componentRoot);
                if (parent && ret.parentNode !== parent) parent.appendChild(ret);
                if (!--diffLevel) {
                    hydrating = !1;
                    if (!componentRoot) flushMounts();
                }
                return ret;
            }
            function idiff(dom, vnode, context, mountAll, componentRoot) {
                var out = dom, prevSvgMode = isSvgMode;
                if (null == vnode || 'boolean' == typeof vnode) vnode = '';
                if ('string' == typeof vnode || 'number' == typeof vnode) {
                    if (dom && void 0 !== dom.splitText && dom.parentNode && (!dom._component || componentRoot)) {
                        if (dom.nodeValue != vnode) dom.nodeValue = vnode;
                    } else {
                        out = document.createTextNode(vnode);
                        if (dom) {
                            if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
                            recollectNodeTree(dom, !0);
                        }
                    }
                    out.__preactattr_ = !0;
                    return out;
                }
                var vnodeName = vnode.nodeName;
                if ('function' == typeof vnodeName) return buildComponentFromVNode(dom, vnode, context, mountAll);
                isSvgMode = 'svg' === vnodeName ? !0 : 'foreignObject' === vnodeName ? !1 : isSvgMode;
                vnodeName = String(vnodeName);
                if (!dom || !isNamedNode(dom, vnodeName)) {
                    out = createNode(vnodeName, isSvgMode);
                    if (dom) {
                        while (dom.firstChild) out.appendChild(dom.firstChild);
                        if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
                        recollectNodeTree(dom, !0);
                    }
                }
                var fc = out.firstChild, props = out.__preactattr_, vchildren = vnode.children;
                if (null == props) {
                    props = out.__preactattr_ = {};
                    for (var a = out.attributes, i = a.length; i--; ) props[a[i].name] = a[i].value;
                }
                if (!hydrating && vchildren && 1 === vchildren.length && 'string' == typeof vchildren[0] && null != fc && void 0 !== fc.splitText && null == fc.nextSibling) {
                    if (fc.nodeValue != vchildren[0]) fc.nodeValue = vchildren[0];
                } else if (vchildren && vchildren.length || null != fc) innerDiffNode(out, vchildren, context, mountAll, hydrating || null != props.dangerouslySetInnerHTML);
                diffAttributes(out, vnode.attributes, props);
                isSvgMode = prevSvgMode;
                return out;
            }
            function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {
                var j, c, f, vchild, child, originalChildren = dom.childNodes, children = [], keyed = {}, keyedLen = 0, min = 0, len = originalChildren.length, childrenLen = 0, vlen = vchildren ? vchildren.length : 0;
                if (0 !== len) for (var i = 0; i < len; i++) {
                    var _child = originalChildren[i], props = _child.__preactattr_, key = vlen && props ? _child._component ? _child._component.__k : props.key : null;
                    if (null != key) {
                        keyedLen++;
                        keyed[key] = _child;
                    } else if (props || (void 0 !== _child.splitText ? isHydrating ? _child.nodeValue.trim() : !0 : isHydrating)) children[childrenLen++] = _child;
                }
                if (0 !== vlen) for (var i = 0; i < vlen; i++) {
                    vchild = vchildren[i];
                    child = null;
                    var key = vchild.key;
                    if (null != key) {
                        if (keyedLen && void 0 !== keyed[key]) {
                            child = keyed[key];
                            keyed[key] = void 0;
                            keyedLen--;
                        }
                    } else if (!child && min < childrenLen) for (j = min; j < childrenLen; j++) if (void 0 !== children[j] && isSameNodeType(c = children[j], vchild, isHydrating)) {
                        child = c;
                        children[j] = void 0;
                        if (j === childrenLen - 1) childrenLen--;
                        if (j === min) min++;
                        break;
                    }
                    child = idiff(child, vchild, context, mountAll);
                    f = originalChildren[i];
                    if (child && child !== dom && child !== f) if (null == f) dom.appendChild(child); else if (child === f.nextSibling) removeNode(f); else dom.insertBefore(child, f);
                }
                if (keyedLen) for (var i in keyed) if (void 0 !== keyed[i]) recollectNodeTree(keyed[i], !1);
                while (min <= childrenLen) if (void 0 !== (child = children[childrenLen--])) recollectNodeTree(child, !1);
            }
            function recollectNodeTree(node, unmountOnly) {
                var component = node._component;
                if (component) unmountComponent(component); else {
                    if (null != node.__preactattr_ && node.__preactattr_.ref) node.__preactattr_.ref(null);
                    if (!1 === unmountOnly || null == node.__preactattr_) removeNode(node);
                    removeChildren(node);
                }
            }
            function removeChildren(node) {
                node = node.lastChild;
                while (node) {
                    var next = node.previousSibling;
                    recollectNodeTree(node, !0);
                    node = next;
                }
            }
            function diffAttributes(dom, attrs, old) {
                var name;
                for (name in old) if ((!attrs || null == attrs[name]) && null != old[name]) setAccessor(dom, name, old[name], old[name] = void 0, isSvgMode);
                for (name in attrs) if (!('children' === name || 'innerHTML' === name || name in old && attrs[name] === ('value' === name || 'checked' === name ? dom[name] : old[name]))) setAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode);
            }
            function collectComponent(component) {
                var name = component.constructor.name;
                (components[name] || (components[name] = [])).push(component);
            }
            function createComponent(Ctor, props, context) {
                var inst, list = components[Ctor.name];
                if (Ctor.prototype && Ctor.prototype.render) {
                    inst = new Ctor(props, context);
                    Component.call(inst, props, context);
                } else {
                    inst = new Component(props, context);
                    inst.constructor = Ctor;
                    inst.render = doRender;
                }
                if (list) for (var i = list.length; i--; ) if (list[i].constructor === Ctor) {
                    inst.__b = list[i].__b;
                    list.splice(i, 1);
                    break;
                }
                return inst;
            }
            function doRender(props, state, context) {
                return this.constructor(props, context);
            }
            function setComponentProps(component, props, opts, context, mountAll) {
                if (!component.__x) {
                    component.__x = !0;
                    if (component.__r = props.ref) delete props.ref;
                    if (component.__k = props.key) delete props.key;
                    if (!component.base || mountAll) {
                        if (component.componentWillMount) component.componentWillMount();
                    } else if (component.componentWillReceiveProps) component.componentWillReceiveProps(props, context);
                    if (context && context !== component.context) {
                        if (!component.__c) component.__c = component.context;
                        component.context = context;
                    }
                    if (!component.__p) component.__p = component.props;
                    component.props = props;
                    component.__x = !1;
                    if (0 !== opts) if (1 === opts || !1 !== options.syncComponentUpdates || !component.base) renderComponent(component, 1, mountAll); else enqueueRender(component);
                    if (component.__r) component.__r(component);
                }
            }
            function renderComponent(component, opts, mountAll, isChild) {
                if (!component.__x) {
                    var rendered, inst, cbase, props = component.props, state = component.state, context = component.context, previousProps = component.__p || props, previousState = component.__s || state, previousContext = component.__c || context, isUpdate = component.base, nextBase = component.__b, initialBase = isUpdate || nextBase, initialChildComponent = component._component, skip = !1;
                    if (isUpdate) {
                        component.props = previousProps;
                        component.state = previousState;
                        component.context = previousContext;
                        if (2 !== opts && component.shouldComponentUpdate && !1 === component.shouldComponentUpdate(props, state, context)) skip = !0; else if (component.componentWillUpdate) component.componentWillUpdate(props, state, context);
                        component.props = props;
                        component.state = state;
                        component.context = context;
                    }
                    component.__p = component.__s = component.__c = component.__b = null;
                    component.__d = !1;
                    if (!skip) {
                        rendered = component.render(props, state, context);
                        if (component.getChildContext) context = extend(extend({}, context), component.getChildContext());
                        var toUnmount, base, childComponent = rendered && rendered.nodeName;
                        if ('function' == typeof childComponent) {
                            var childProps = getNodeProps(rendered);
                            inst = initialChildComponent;
                            if (inst && inst.constructor === childComponent && childProps.key == inst.__k) setComponentProps(inst, childProps, 1, context, !1); else {
                                toUnmount = inst;
                                component._component = inst = createComponent(childComponent, childProps, context);
                                inst.__b = inst.__b || nextBase;
                                inst.__u = component;
                                setComponentProps(inst, childProps, 0, context, !1);
                                renderComponent(inst, 1, mountAll, !0);
                            }
                            base = inst.base;
                        } else {
                            cbase = initialBase;
                            toUnmount = initialChildComponent;
                            if (toUnmount) cbase = component._component = null;
                            if (initialBase || 1 === opts) {
                                if (cbase) cbase._component = null;
                                base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, !0);
                            }
                        }
                        if (initialBase && base !== initialBase && inst !== initialChildComponent) {
                            var baseParent = initialBase.parentNode;
                            if (baseParent && base !== baseParent) {
                                baseParent.replaceChild(base, initialBase);
                                if (!toUnmount) {
                                    initialBase._component = null;
                                    recollectNodeTree(initialBase, !1);
                                }
                            }
                        }
                        if (toUnmount) unmountComponent(toUnmount);
                        component.base = base;
                        if (base && !isChild) {
                            var componentRef = component, t = component;
                            while (t = t.__u) (componentRef = t).base = base;
                            base._component = componentRef;
                            base._componentConstructor = componentRef.constructor;
                        }
                    }
                    if (!isUpdate || mountAll) mounts.unshift(component); else if (!skip) {
                        if (component.componentDidUpdate) component.componentDidUpdate(previousProps, previousState, previousContext);
                        if (options.afterUpdate) options.afterUpdate(component);
                    }
                    if (null != component.__h) while (component.__h.length) component.__h.pop().call(component);
                    if (!diffLevel && !isChild) flushMounts();
                }
            }
            function buildComponentFromVNode(dom, vnode, context, mountAll) {
                var c = dom && dom._component, originalComponent = c, oldDom = dom, isDirectOwner = c && dom._componentConstructor === vnode.nodeName, isOwner = isDirectOwner, props = getNodeProps(vnode);
                while (c && !isOwner && (c = c.__u)) isOwner = c.constructor === vnode.nodeName;
                if (c && isOwner && (!mountAll || c._component)) {
                    setComponentProps(c, props, 3, context, mountAll);
                    dom = c.base;
                } else {
                    if (originalComponent && !isDirectOwner) {
                        unmountComponent(originalComponent);
                        dom = oldDom = null;
                    }
                    c = createComponent(vnode.nodeName, props, context);
                    if (dom && !c.__b) {
                        c.__b = dom;
                        oldDom = null;
                    }
                    setComponentProps(c, props, 1, context, mountAll);
                    dom = c.base;
                    if (oldDom && dom !== oldDom) {
                        oldDom._component = null;
                        recollectNodeTree(oldDom, !1);
                    }
                }
                return dom;
            }
            function unmountComponent(component) {
                if (options.beforeUnmount) options.beforeUnmount(component);
                var base = component.base;
                component.__x = !0;
                if (component.componentWillUnmount) component.componentWillUnmount();
                component.base = null;
                var inner = component._component;
                if (inner) unmountComponent(inner); else if (base) {
                    if (base.__preactattr_ && base.__preactattr_.ref) base.__preactattr_.ref(null);
                    component.__b = base;
                    removeNode(base);
                    collectComponent(component);
                    removeChildren(base);
                }
                if (component.__r) component.__r(null);
            }
            function Component(props, context) {
                this.__d = !0;
                this.context = context;
                this.props = props;
                this.state = this.state || {};
            }
            function render(vnode, parent, merge) {
                return diff(merge, vnode, {}, !1, parent, !1);
            }
            var options = {};
            var stack = [];
            var EMPTY_CHILDREN = [];
            var defer = 'function' == typeof Promise ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout;
            var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;
            var items = [];
            var mounts = [];
            var diffLevel = 0;
            var isSvgMode = !1;
            var hydrating = !1;
            var components = {};
            extend(Component.prototype, {
                setState: function(state, callback) {
                    var s = this.state;
                    if (!this.__s) this.__s = extend({}, s);
                    extend(s, 'function' == typeof state ? state(s, this.props) : state);
                    if (callback) (this.__h = this.__h || []).push(callback);
                    enqueueRender(this);
                },
                forceUpdate: function(callback) {
                    if (callback) (this.__h = this.__h || []).push(callback);
                    renderComponent(this, 2);
                },
                render: function() {}
            });
            var preact = {
                h: h,
                createElement: h,
                cloneElement: cloneElement,
                Component: Component,
                render: render,
                rerender: rerender,
                options: options
            };
            if ('undefined' != typeof module) module.exports = preact; else self.preact = preact;
        }();

    },{}],47:[function(require,module,exports){
        module.exports = prettierBytes

        function prettierBytes (num) {
            if (typeof num !== 'number' || isNaN(num)) {
                throw new TypeError('Expected a number, got ' + typeof num)
            }

            var neg = num < 0
            var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']

            if (neg) {
                num = -num
            }

            if (num < 1) {
                return (neg ? '-' : '') + num + ' B'
            }

            var exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), units.length - 1)
            num = Number(num / Math.pow(1000, exponent))
            var unit = units[exponent]

            if (num >= 10 || num % 1 === 0) {
                // Do not show decimals when the number is two-digit, or if the number has no
                // decimal component.
                return (neg ? '-' : '') + num.toFixed(0) + ' ' + unit
            } else {
                return (neg ? '-' : '') + num.toFixed(1) + ' ' + unit
            }
        }

    },{}],48:[function(require,module,exports){
        'use strict';

        var has = Object.prototype.hasOwnProperty;

        /**
         * Decode a URI encoded string.
         *
         * @param {String} input The URI encoded string.
         * @returns {String} The decoded string.
         * @api private
         */
        function decode(input) {
            return decodeURIComponent(input.replace(/\+/g, ' '));
        }

        /**
         * Simple query string parser.
         *
         * @param {String} query The query string that needs to be parsed.
         * @returns {Object}
         * @api public
         */
        function querystring(query) {
            var parser = /([^=?&]+)=?([^&]*)/g
                , result = {}
                , part;

            //
            // Little nifty parsing hack, leverage the fact that RegExp.exec increments
            // the lastIndex property so we can continue executing this loop until we've
            // parsed all results.
            //
            for (;
                part = parser.exec(query);
                result[decode(part[1])] = decode(part[2])
            );

            return result;
        }

        /**
         * Transform a query string to an object.
         *
         * @param {Object} obj Object that should be transformed.
         * @param {String} prefix Optional prefix.
         * @returns {String}
         * @api public
         */
        function querystringify(obj, prefix) {
            prefix = prefix || '';

            var pairs = [];

            //
            // Optionally prefix with a '?' if needed
            //
            if ('string' !== typeof prefix) prefix = '?';

            for (var key in obj) {
                if (has.call(obj, key)) {
                    pairs.push(encodeURIComponent(key) +'='+ encodeURIComponent(obj[key]));
                }
            }

            return pairs.length ? prefix + pairs.join('&') : '';
        }

//
// Expose the module.
//
        exports.stringify = querystringify;
        exports.parse = querystring;

    },{}],49:[function(require,module,exports){
        'use strict';

        /**
         * Check if we're required to add a port number.
         *
         * @see https://url.spec.whatwg.org/#default-port
         * @param {Number|String} port Port number we need to check
         * @param {String} protocol Protocol we need to check against.
         * @returns {Boolean} Is it a default port for the given protocol
         * @api private
         */
        module.exports = function required(port, protocol) {
            protocol = protocol.split(':')[0];
            port = +port;

            if (!port) return false;

            switch (protocol) {
                case 'http':
                case 'ws':
                    return port !== 80;

                case 'https':
                case 'wss':
                    return port !== 443;

                case 'ftp':
                    return port !== 21;

                case 'gopher':
                    return port !== 70;

                case 'file':
                    return false;
            }

            return port !== 0;
        };

    },{}],50:[function(require,module,exports){
// Copyright 2014 Simon Lydell
// X11 (â€œMITâ€) Licensed. (See LICENSE.)

        void (function(root, factory) {
            if (typeof define === "function" && define.amd) {
                define(factory)
            } else if (typeof exports === "object") {
                module.exports = factory()
            } else {
                root.resolveUrl = factory()
            }
        }(this, function() {

            function resolveUrl(/* ...urls */) {
                var numUrls = arguments.length

                if (numUrls === 0) {
                    throw new Error("resolveUrl requires at least one argument; got none.")
                }

                var base = document.createElement("base")
                base.href = arguments[0]

                if (numUrls === 1) {
                    return base.href
                }

                var head = document.getElementsByTagName("head")[0]
                head.insertBefore(base, head.firstChild)

                var a = document.createElement("a")
                var resolved

                for (var index = 1; index < numUrls; index++) {
                    a.href = arguments[index]
                    resolved = a.href
                    base.href = resolved
                }

                head.removeChild(base)

                return resolved
            }

            return resolveUrl

        }));

    },{}],51:[function(require,module,exports){
        (function (process){
            module.exports = function (tasks, cb) {
                var results, pending, keys
                var isSync = true

                if (Array.isArray(tasks)) {
                    results = []
                    pending = tasks.length
                } else {
                    keys = Object.keys(tasks)
                    results = {}
                    pending = keys.length
                }

                function done (err) {
                    function end () {
                        if (cb) cb(err, results)
                        cb = null
                    }
                    if (isSync) process.nextTick(end)
                    else end()
                }

                function each (i, err, result) {
                    results[i] = result
                    if (--pending === 0 || err) {
                        done(err)
                    }
                }

                if (!pending) {
                    // empty
                    done(null)
                } else if (keys) {
                    // object
                    keys.forEach(function (key) {
                        tasks[key](function (err, result) { each(key, err, result) })
                    })
                } else {
                    // array
                    tasks.forEach(function (task, i) {
                        task(function (err, result) { each(i, err, result) })
                    })
                }

                isSync = false
            }

        }).call(this,require('_process'))

    },{"_process":6}],52:[function(require,module,exports){

        /**
         * Module dependencies.
         */

        var url = require('./url');
        var parser = require('socket.io-parser');
        var Manager = require('./manager');
        var debug = require('debug')('socket.io-client');

        /**
         * Module exports.
         */

        module.exports = exports = lookup;

        /**
         * Managers cache.
         */

        var cache = exports.managers = {};

        /**
         * Looks up an existing `Manager` for multiplexing.
         * If the user summons:
         *
         *   `io('http://localhost/a');`
         *   `io('http://localhost/b');`
         *
         * We reuse the existing instance based on same scheme/port/host,
         * and we initialize sockets for each namespace.
         *
         * @api public
         */

        function lookup (uri, opts) {
            if (typeof uri === 'object') {
                opts = uri;
                uri = undefined;
            }

            opts = opts || {};

            var parsed = url(uri);
            var source = parsed.source;
            var id = parsed.id;
            var path = parsed.path;
            var sameNamespace = cache[id] && path in cache[id].nsps;
            var newConnection = opts.forceNew || opts['force new connection'] ||
                false === opts.multiplex || sameNamespace;

            var io;

            if (newConnection) {
                debug('ignoring socket cache for %s', source);
                io = Manager(source, opts);
            } else {
                if (!cache[id]) {
                    debug('new io instance for %s', source);
                    cache[id] = Manager(source, opts);
                }
                io = cache[id];
            }
            if (parsed.query && !opts.query) {
                opts.query = parsed.query;
            }
            return io.socket(parsed.path, opts);
        }

        /**
         * Protocol version.
         *
         * @api public
         */

        exports.protocol = parser.protocol;

        /**
         * `connect`.
         *
         * @param {String} uri
         * @api public
         */

        exports.connect = lookup;

        /**
         * Expose constructors for standalone build.
         *
         * @api public
         */

        exports.Manager = require('./manager');
        exports.Socket = require('./socket');

    },{"./manager":53,"./socket":55,"./url":56,"debug":14,"socket.io-parser":58}],53:[function(require,module,exports){

        /**
         * Module dependencies.
         */

        var eio = require('engine.io-client');
        var Socket = require('./socket');
        var Emitter = require('component-emitter');
        var parser = require('socket.io-parser');
        var on = require('./on');
        var bind = require('component-bind');
        var debug = require('debug')('socket.io-client:manager');
        var indexOf = require('indexof');
        var Backoff = require('backo2');

        /**
         * IE6+ hasOwnProperty
         */

        var has = Object.prototype.hasOwnProperty;

        /**
         * Module exports
         */

        module.exports = Manager;

        /**
         * `Manager` constructor.
         *
         * @param {String} engine instance or engine uri/opts
         * @param {Object} options
         * @api public
         */

        function Manager (uri, opts) {
            if (!(this instanceof Manager)) return new Manager(uri, opts);
            if (uri && ('object' === typeof uri)) {
                opts = uri;
                uri = undefined;
            }
            opts = opts || {};

            opts.path = opts.path || '/socket.io';
            this.nsps = {};
            this.subs = [];
            this.opts = opts;
            this.reconnection(opts.reconnection !== false);
            this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
            this.reconnectionDelay(opts.reconnectionDelay || 1000);
            this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
            this.randomizationFactor(opts.randomizationFactor || 0.5);
            this.backoff = new Backoff({
                min: this.reconnectionDelay(),
                max: this.reconnectionDelayMax(),
                jitter: this.randomizationFactor()
            });
            this.timeout(null == opts.timeout ? 20000 : opts.timeout);
            this.readyState = 'closed';
            this.uri = uri;
            this.connecting = [];
            this.lastPing = null;
            this.encoding = false;
            this.packetBuffer = [];
            var _parser = opts.parser || parser;
            this.encoder = new _parser.Encoder();
            this.decoder = new _parser.Decoder();
            this.autoConnect = opts.autoConnect !== false;
            if (this.autoConnect) this.open();
        }

        /**
         * Propagate given event to sockets and emit on `this`
         *
         * @api private
         */

        Manager.prototype.emitAll = function () {
            this.emit.apply(this, arguments);
            for (var nsp in this.nsps) {
                if (has.call(this.nsps, nsp)) {
                    this.nsps[nsp].emit.apply(this.nsps[nsp], arguments);
                }
            }
        };

        /**
         * Update `socket.id` of all sockets
         *
         * @api private
         */

        Manager.prototype.updateSocketIds = function () {
            for (var nsp in this.nsps) {
                if (has.call(this.nsps, nsp)) {
                    this.nsps[nsp].id = this.generateId(nsp);
                }
            }
        };

        /**
         * generate `socket.id` for the given `nsp`
         *
         * @param {String} nsp
         * @return {String}
         * @api private
         */

        Manager.prototype.generateId = function (nsp) {
            return (nsp === '/' ? '' : (nsp + '#')) + this.engine.id;
        };

        /**
         * Mix in `Emitter`.
         */

        Emitter(Manager.prototype);

        /**
         * Sets the `reconnection` config.
         *
         * @param {Boolean} true/false if it should automatically reconnect
         * @return {Manager} self or value
         * @api public
         */

        Manager.prototype.reconnection = function (v) {
            if (!arguments.length) return this._reconnection;
            this._reconnection = !!v;
            return this;
        };

        /**
         * Sets the reconnection attempts config.
         *
         * @param {Number} max reconnection attempts before giving up
         * @return {Manager} self or value
         * @api public
         */

        Manager.prototype.reconnectionAttempts = function (v) {
            if (!arguments.length) return this._reconnectionAttempts;
            this._reconnectionAttempts = v;
            return this;
        };

        /**
         * Sets the delay between reconnections.
         *
         * @param {Number} delay
         * @return {Manager} self or value
         * @api public
         */

        Manager.prototype.reconnectionDelay = function (v) {
            if (!arguments.length) return this._reconnectionDelay;
            this._reconnectionDelay = v;
            this.backoff && this.backoff.setMin(v);
            return this;
        };

        Manager.prototype.randomizationFactor = function (v) {
            if (!arguments.length) return this._randomizationFactor;
            this._randomizationFactor = v;
            this.backoff && this.backoff.setJitter(v);
            return this;
        };

        /**
         * Sets the maximum delay between reconnections.
         *
         * @param {Number} delay
         * @return {Manager} self or value
         * @api public
         */

        Manager.prototype.reconnectionDelayMax = function (v) {
            if (!arguments.length) return this._reconnectionDelayMax;
            this._reconnectionDelayMax = v;
            this.backoff && this.backoff.setMax(v);
            return this;
        };

        /**
         * Sets the connection timeout. `false` to disable
         *
         * @return {Manager} self or value
         * @api public
         */

        Manager.prototype.timeout = function (v) {
            if (!arguments.length) return this._timeout;
            this._timeout = v;
            return this;
        };

        /**
         * Starts trying to reconnect if reconnection is enabled and we have not
         * started reconnecting yet
         *
         * @api private
         */

        Manager.prototype.maybeReconnectOnOpen = function () {
            // Only try to reconnect if it's the first time we're connecting
            if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) {
                // keeps reconnection from firing twice for the same reconnection loop
                this.reconnect();
            }
        };

        /**
         * Sets the current transport `socket`.
         *
         * @param {Function} optional, callback
         * @return {Manager} self
         * @api public
         */

        Manager.prototype.open =
            Manager.prototype.connect = function (fn, opts) {
                debug('readyState %s', this.readyState);
                if (~this.readyState.indexOf('open')) return this;

                debug('opening %s', this.uri);
                this.engine = eio(this.uri, this.opts);
                var socket = this.engine;
                var self = this;
                this.readyState = 'opening';
                this.skipReconnect = false;

                // emit `open`
                var openSub = on(socket, 'open', function () {
                    self.onopen();
                    fn && fn();
                });

                // emit `connect_error`
                var errorSub = on(socket, 'error', function (data) {
                    debug('connect_error');
                    self.cleanup();
                    self.readyState = 'closed';
                    self.emitAll('connect_error', data);
                    if (fn) {
                        var err = new Error('Connection error');
                        err.data = data;
                        fn(err);
                    } else {
                        // Only do this if there is no fn to handle the error
                        self.maybeReconnectOnOpen();
                    }
                });

                // emit `connect_timeout`
                if (false !== this._timeout) {
                    var timeout = this._timeout;
                    debug('connect attempt will timeout after %d', timeout);

                    // set timer
                    var timer = setTimeout(function () {
                        debug('connect attempt timed out after %d', timeout);
                        openSub.destroy();
                        socket.close();
                        socket.emit('error', 'timeout');
                        self.emitAll('connect_timeout', timeout);
                    }, timeout);

                    this.subs.push({
                        destroy: function () {
                            clearTimeout(timer);
                        }
                    });
                }

                this.subs.push(openSub);
                this.subs.push(errorSub);

                return this;
            };

        /**
         * Called upon transport open.
         *
         * @api private
         */

        Manager.prototype.onopen = function () {
            debug('open');

            // clear old subs
            this.cleanup();

            // mark as open
            this.readyState = 'open';
            this.emit('open');

            // add new subs
            var socket = this.engine;
            this.subs.push(on(socket, 'data', bind(this, 'ondata')));
            this.subs.push(on(socket, 'ping', bind(this, 'onping')));
            this.subs.push(on(socket, 'pong', bind(this, 'onpong')));
            this.subs.push(on(socket, 'error', bind(this, 'onerror')));
            this.subs.push(on(socket, 'close', bind(this, 'onclose')));
            this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
        };

        /**
         * Called upon a ping.
         *
         * @api private
         */

        Manager.prototype.onping = function () {
            this.lastPing = new Date();
            this.emitAll('ping');
        };

        /**
         * Called upon a packet.
         *
         * @api private
         */

        Manager.prototype.onpong = function () {
            this.emitAll('pong', new Date() - this.lastPing);
        };

        /**
         * Called with data.
         *
         * @api private
         */

        Manager.prototype.ondata = function (data) {
            this.decoder.add(data);
        };

        /**
         * Called when parser fully decodes a packet.
         *
         * @api private
         */

        Manager.prototype.ondecoded = function (packet) {
            this.emit('packet', packet);
        };

        /**
         * Called upon socket error.
         *
         * @api private
         */

        Manager.prototype.onerror = function (err) {
            debug('error', err);
            this.emitAll('error', err);
        };

        /**
         * Creates a new socket for the given `nsp`.
         *
         * @return {Socket}
         * @api public
         */

        Manager.prototype.socket = function (nsp, opts) {
            var socket = this.nsps[nsp];
            if (!socket) {
                socket = new Socket(this, nsp, opts);
                this.nsps[nsp] = socket;
                var self = this;
                socket.on('connecting', onConnecting);
                socket.on('connect', function () {
                    socket.id = self.generateId(nsp);
                });

                if (this.autoConnect) {
                    // manually call here since connecting event is fired before listening
                    onConnecting();
                }
            }

            function onConnecting () {
                if (!~indexOf(self.connecting, socket)) {
                    self.connecting.push(socket);
                }
            }

            return socket;
        };

        /**
         * Called upon a socket close.
         *
         * @param {Socket} socket
         */

        Manager.prototype.destroy = function (socket) {
            var index = indexOf(this.connecting, socket);
            if (~index) this.connecting.splice(index, 1);
            if (this.connecting.length) return;

            this.close();
        };

        /**
         * Writes a packet.
         *
         * @param {Object} packet
         * @api private
         */

        Manager.prototype.packet = function (packet) {
            debug('writing packet %j', packet);
            var self = this;
            if (packet.query && packet.type === 0) packet.nsp += '?' + packet.query;

            if (!self.encoding) {
                // encode, then write to engine with result
                self.encoding = true;
                this.encoder.encode(packet, function (encodedPackets) {
                    for (var i = 0; i < encodedPackets.length; i++) {
                        self.engine.write(encodedPackets[i], packet.options);
                    }
                    self.encoding = false;
                    self.processPacketQueue();
                });
            } else { // add packet to the queue
                self.packetBuffer.push(packet);
            }
        };

        /**
         * If packet buffer is non-empty, begins encoding the
         * next packet in line.
         *
         * @api private
         */

        Manager.prototype.processPacketQueue = function () {
            if (this.packetBuffer.length > 0 && !this.encoding) {
                var pack = this.packetBuffer.shift();
                this.packet(pack);
            }
        };

        /**
         * Clean up transport subscriptions and packet buffer.
         *
         * @api private
         */

        Manager.prototype.cleanup = function () {
            debug('cleanup');

            var subsLength = this.subs.length;
            for (var i = 0; i < subsLength; i++) {
                var sub = this.subs.shift();
                sub.destroy();
            }

            this.packetBuffer = [];
            this.encoding = false;
            this.lastPing = null;

            this.decoder.destroy();
        };

        /**
         * Close the current socket.
         *
         * @api private
         */

        Manager.prototype.close =
            Manager.prototype.disconnect = function () {
                debug('disconnect');
                this.skipReconnect = true;
                this.reconnecting = false;
                if ('opening' === this.readyState) {
                    // `onclose` will not fire because
                    // an open event never happened
                    this.cleanup();
                }
                this.backoff.reset();
                this.readyState = 'closed';
                if (this.engine) this.engine.close();
            };

        /**
         * Called upon engine close.
         *
         * @api private
         */

        Manager.prototype.onclose = function (reason) {
            debug('onclose');

            this.cleanup();
            this.backoff.reset();
            this.readyState = 'closed';
            this.emit('close', reason);

            if (this._reconnection && !this.skipReconnect) {
                this.reconnect();
            }
        };

        /**
         * Attempt a reconnection.
         *
         * @api private
         */

        Manager.prototype.reconnect = function () {
            if (this.reconnecting || this.skipReconnect) return this;

            var self = this;

            if (this.backoff.attempts >= this._reconnectionAttempts) {
                debug('reconnect failed');
                this.backoff.reset();
                this.emitAll('reconnect_failed');
                this.reconnecting = false;
            } else {
                var delay = this.backoff.duration();
                debug('will wait %dms before reconnect attempt', delay);

                this.reconnecting = true;
                var timer = setTimeout(function () {
                    if (self.skipReconnect) return;

                    debug('attempting reconnect');
                    self.emitAll('reconnect_attempt', self.backoff.attempts);
                    self.emitAll('reconnecting', self.backoff.attempts);

                    // check again for the case socket closed in above events
                    if (self.skipReconnect) return;

                    self.open(function (err) {
                        if (err) {
                            debug('reconnect attempt error');
                            self.reconnecting = false;
                            self.reconnect();
                            self.emitAll('reconnect_error', err.data);
                        } else {
                            debug('reconnect success');
                            self.onreconnect();
                        }
                    });
                }, delay);

                this.subs.push({
                    destroy: function () {
                        clearTimeout(timer);
                    }
                });
            }
        };

        /**
         * Called upon successful reconnect.
         *
         * @api private
         */

        Manager.prototype.onreconnect = function () {
            var attempt = this.backoff.attempts;
            this.reconnecting = false;
            this.backoff.reset();
            this.updateSocketIds();
            this.emitAll('reconnect', attempt);
        };

    },{"./on":54,"./socket":55,"backo2":2,"component-bind":8,"component-emitter":9,"debug":14,"engine.io-client":17,"indexof":38,"socket.io-parser":58}],54:[function(require,module,exports){

        /**
         * Module exports.
         */

        module.exports = on;

        /**
         * Helper for subscriptions.
         *
         * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
         * @param {String} event name
         * @param {Function} callback
         * @api public
         */

        function on (obj, ev, fn) {
            obj.on(ev, fn);
            return {
                destroy: function () {
                    obj.removeListener(ev, fn);
                }
            };
        }

    },{}],55:[function(require,module,exports){

        /**
         * Module dependencies.
         */

        var parser = require('socket.io-parser');
        var Emitter = require('component-emitter');
        var toArray = require('to-array');
        var on = require('./on');
        var bind = require('component-bind');
        var debug = require('debug')('socket.io-client:socket');
        var parseqs = require('parseqs');

        /**
         * Module exports.
         */

        module.exports = exports = Socket;

        /**
         * Internal events (blacklisted).
         * These events can't be emitted by the user.
         *
         * @api private
         */

        var events = {
            connect: 1,
            connect_error: 1,
            connect_timeout: 1,
            connecting: 1,
            disconnect: 1,
            error: 1,
            reconnect: 1,
            reconnect_attempt: 1,
            reconnect_failed: 1,
            reconnect_error: 1,
            reconnecting: 1,
            ping: 1,
            pong: 1
        };

        /**
         * Shortcut to `Emitter#emit`.
         */

        var emit = Emitter.prototype.emit;

        /**
         * `Socket` constructor.
         *
         * @api public
         */

        function Socket (io, nsp, opts) {
            this.io = io;
            this.nsp = nsp;
            this.json = this; // compat
            this.ids = 0;
            this.acks = {};
            this.receiveBuffer = [];
            this.sendBuffer = [];
            this.connected = false;
            this.disconnected = true;
            if (opts && opts.query) {
                this.query = opts.query;
            }
            if (this.io.autoConnect) this.open();
        }

        /**
         * Mix in `Emitter`.
         */

        Emitter(Socket.prototype);

        /**
         * Subscribe to open, close and packet events
         *
         * @api private
         */

        Socket.prototype.subEvents = function () {
            if (this.subs) return;

            var io = this.io;
            this.subs = [
                on(io, 'open', bind(this, 'onopen')),
                on(io, 'packet', bind(this, 'onpacket')),
                on(io, 'close', bind(this, 'onclose'))
            ];
        };

        /**
         * "Opens" the socket.
         *
         * @api public
         */

        Socket.prototype.open =
            Socket.prototype.connect = function () {
                if (this.connected) return this;

                this.subEvents();
                this.io.open(); // ensure open
                if ('open' === this.io.readyState) this.onopen();
                this.emit('connecting');
                return this;
            };

        /**
         * Sends a `message` event.
         *
         * @return {Socket} self
         * @api public
         */

        Socket.prototype.send = function () {
            var args = toArray(arguments);
            args.unshift('message');
            this.emit.apply(this, args);
            return this;
        };

        /**
         * Override `emit`.
         * If the event is in `events`, it's emitted normally.
         *
         * @param {String} event name
         * @return {Socket} self
         * @api public
         */

        Socket.prototype.emit = function (ev) {
            if (events.hasOwnProperty(ev)) {
                emit.apply(this, arguments);
                return this;
            }

            var args = toArray(arguments);
            var packet = { type: parser.EVENT, data: args };

            packet.options = {};
            packet.options.compress = !this.flags || false !== this.flags.compress;

            // event ack callback
            if ('function' === typeof args[args.length - 1]) {
                debug('emitting packet with ack id %d', this.ids);
                this.acks[this.ids] = args.pop();
                packet.id = this.ids++;
            }

            if (this.connected) {
                this.packet(packet);
            } else {
                this.sendBuffer.push(packet);
            }

            delete this.flags;

            return this;
        };

        /**
         * Sends a packet.
         *
         * @param {Object} packet
         * @api private
         */

        Socket.prototype.packet = function (packet) {
            packet.nsp = this.nsp;
            this.io.packet(packet);
        };

        /**
         * Called upon engine `open`.
         *
         * @api private
         */

        Socket.prototype.onopen = function () {
            debug('transport is open - connecting');

            // write connect packet if necessary
            if ('/' !== this.nsp) {
                if (this.query) {
                    var query = typeof this.query === 'object' ? parseqs.encode(this.query) : this.query;
                    debug('sending connect packet with query %s', query);
                    this.packet({type: parser.CONNECT, query: query});
                } else {
                    this.packet({type: parser.CONNECT});
                }
            }
        };

        /**
         * Called upon engine `close`.
         *
         * @param {String} reason
         * @api private
         */

        Socket.prototype.onclose = function (reason) {
            debug('close (%s)', reason);
            this.connected = false;
            this.disconnected = true;
            delete this.id;
            this.emit('disconnect', reason);
        };

        /**
         * Called with socket packet.
         *
         * @param {Object} packet
         * @api private
         */

        Socket.prototype.onpacket = function (packet) {
            if (packet.nsp !== this.nsp) return;

            switch (packet.type) {
                case parser.CONNECT:
                    this.onconnect();
                    break;

                case parser.EVENT:
                    this.onevent(packet);
                    break;

                case parser.BINARY_EVENT:
                    this.onevent(packet);
                    break;

                case parser.ACK:
                    this.onack(packet);
                    break;

                case parser.BINARY_ACK:
                    this.onack(packet);
                    break;

                case parser.DISCONNECT:
                    this.ondisconnect();
                    break;

                case parser.ERROR:
                    this.emit('error', packet.data);
                    break;
            }
        };

        /**
         * Called upon a server event.
         *
         * @param {Object} packet
         * @api private
         */

        Socket.prototype.onevent = function (packet) {
            var args = packet.data || [];
            debug('emitting event %j', args);

            if (null != packet.id) {
                debug('attaching ack callback to event');
                args.push(this.ack(packet.id));
            }

            if (this.connected) {
                emit.apply(this, args);
            } else {
                this.receiveBuffer.push(args);
            }
        };

        /**
         * Produces an ack callback to emit with an event.
         *
         * @api private
         */

        Socket.prototype.ack = function (id) {
            var self = this;
            var sent = false;
            return function () {
                // prevent double callbacks
                if (sent) return;
                sent = true;
                var args = toArray(arguments);
                debug('sending ack %j', args);

                self.packet({
                    type: parser.ACK,
                    id: id,
                    data: args
                });
            };
        };

        /**
         * Called upon a server acknowlegement.
         *
         * @param {Object} packet
         * @api private
         */

        Socket.prototype.onack = function (packet) {
            var ack = this.acks[packet.id];
            if ('function' === typeof ack) {
                debug('calling ack %s with %j', packet.id, packet.data);
                ack.apply(this, packet.data);
                delete this.acks[packet.id];
            } else {
                debug('bad ack %s', packet.id);
            }
        };

        /**
         * Called upon server connect.
         *
         * @api private
         */

        Socket.prototype.onconnect = function () {
            this.connected = true;
            this.disconnected = false;
            this.emit('connect');
            this.emitBuffered();
        };

        /**
         * Emit buffered events (received and emitted).
         *
         * @api private
         */

        Socket.prototype.emitBuffered = function () {
            var i;
            for (i = 0; i < this.receiveBuffer.length; i++) {
                emit.apply(this, this.receiveBuffer[i]);
            }
            this.receiveBuffer = [];

            for (i = 0; i < this.sendBuffer.length; i++) {
                this.packet(this.sendBuffer[i]);
            }
            this.sendBuffer = [];
        };

        /**
         * Called upon server disconnect.
         *
         * @api private
         */

        Socket.prototype.ondisconnect = function () {
            debug('server disconnect (%s)', this.nsp);
            this.destroy();
            this.onclose('io server disconnect');
        };

        /**
         * Called upon forced client/server side disconnections,
         * this method ensures the manager stops tracking us and
         * that reconnections don't get triggered for this.
         *
         * @api private.
         */

        Socket.prototype.destroy = function () {
            if (this.subs) {
                // clean subscriptions to avoid reconnections
                for (var i = 0; i < this.subs.length; i++) {
                    this.subs[i].destroy();
                }
                this.subs = null;
            }

            this.io.destroy(this);
        };

        /**
         * Disconnects the socket manually.
         *
         * @return {Socket} self
         * @api public
         */

        Socket.prototype.close =
            Socket.prototype.disconnect = function () {
                if (this.connected) {
                    debug('performing disconnect (%s)', this.nsp);
                    this.packet({ type: parser.DISCONNECT });
                }

                // remove socket from pool
                this.destroy();

                if (this.connected) {
                    // fire events
                    this.onclose('io client disconnect');
                }
                return this;
            };

        /**
         * Sets the compress flag.
         *
         * @param {Boolean} if `true`, compresses the sending data
         * @return {Socket} self
         * @api public
         */

        Socket.prototype.compress = function (compress) {
            this.flags = this.flags || {};
            this.flags.compress = compress;
            return this;
        };

    },{"./on":54,"component-bind":8,"component-emitter":9,"debug":14,"parseqs":44,"socket.io-parser":58,"to-array":60}],56:[function(require,module,exports){
        (function (global){

            /**
             * Module dependencies.
             */

            var parseuri = require('parseuri');
            var debug = require('debug')('socket.io-client:url');

            /**
             * Module exports.
             */

            module.exports = url;

            /**
             * URL parser.
             *
             * @param {String} url
             * @param {Object} An object meant to mimic window.location.
             *                 Defaults to window.location.
             * @api public
             */

            function url (uri, loc) {
                var obj = uri;

                // default to window.location
                loc = loc || global.location;
                if (null == uri) uri = loc.protocol + '//' + loc.host;

                // relative path support
                if ('string' === typeof uri) {
                    if ('/' === uri.charAt(0)) {
                        if ('/' === uri.charAt(1)) {
                            uri = loc.protocol + uri;
                        } else {
                            uri = loc.host + uri;
                        }
                    }

                    if (!/^(https?|wss?):\/\//.test(uri)) {
                        debug('protocol-less url %s', uri);
                        if ('undefined' !== typeof loc) {
                            uri = loc.protocol + '//' + uri;
                        } else {
                            uri = 'https://' + uri;
                        }
                    }

                    // parse
                    debug('parse %s', uri);
                    obj = parseuri(uri);
                }

                // make sure we treat `localhost:80` and `localhost` equally
                if (!obj.port) {
                    if (/^(http|ws)$/.test(obj.protocol)) {
                        obj.port = '80';
                    } else if (/^(http|ws)s$/.test(obj.protocol)) {
                        obj.port = '443';
                    }
                }

                obj.path = obj.path || '/';

                var ipv6 = obj.host.indexOf(':') !== -1;
                var host = ipv6 ? '[' + obj.host + ']' : obj.host;

                // define unique id
                obj.id = obj.protocol + '://' + host + ':' + obj.port;
                // define href
                obj.href = obj.protocol + '://' + host + (loc && loc.port === obj.port ? '' : (':' + obj.port));

                return obj;
            }

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"debug":14,"parseuri":45}],57:[function(require,module,exports){
        (function (global){
            /*global Blob,File*/

            /**
             * Module requirements
             */

            var isArray = require('isarray');
            var isBuf = require('./is-buffer');
            var toString = Object.prototype.toString;
            var withNativeBlob = typeof global.Blob === 'function' || toString.call(global.Blob) === '[object BlobConstructor]';
            var withNativeFile = typeof global.File === 'function' || toString.call(global.File) === '[object FileConstructor]';

            /**
             * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
             * Anything with blobs or files should be fed through removeBlobs before coming
             * here.
             *
             * @param {Object} packet - socket.io event packet
             * @return {Object} with deconstructed packet and list of buffers
             * @api public
             */

            exports.deconstructPacket = function(packet) {
                var buffers = [];
                var packetData = packet.data;
                var pack = packet;
                pack.data = _deconstructPacket(packetData, buffers);
                pack.attachments = buffers.length; // number of binary 'attachments'
                return {packet: pack, buffers: buffers};
            };

            function _deconstructPacket(data, buffers) {
                if (!data) return data;

                if (isBuf(data)) {
                    var placeholder = { _placeholder: true, num: buffers.length };
                    buffers.push(data);
                    return placeholder;
                } else if (isArray(data)) {
                    var newData = new Array(data.length);
                    for (var i = 0; i < data.length; i++) {
                        newData[i] = _deconstructPacket(data[i], buffers);
                    }
                    return newData;
                } else if (typeof data === 'object' && !(data instanceof Date)) {
                    var newData = {};
                    for (var key in data) {
                        newData[key] = _deconstructPacket(data[key], buffers);
                    }
                    return newData;
                }
                return data;
            }

            /**
             * Reconstructs a binary packet from its placeholder packet and buffers
             *
             * @param {Object} packet - event packet with placeholders
             * @param {Array} buffers - binary buffers to put in placeholder positions
             * @return {Object} reconstructed packet
             * @api public
             */

            exports.reconstructPacket = function(packet, buffers) {
                packet.data = _reconstructPacket(packet.data, buffers);
                packet.attachments = undefined; // no longer useful
                return packet;
            };

            function _reconstructPacket(data, buffers) {
                if (!data) return data;

                if (data && data._placeholder) {
                    return buffers[data.num]; // appropriate buffer (should be natural order anyway)
                } else if (isArray(data)) {
                    for (var i = 0; i < data.length; i++) {
                        data[i] = _reconstructPacket(data[i], buffers);
                    }
                } else if (typeof data === 'object') {
                    for (var key in data) {
                        data[key] = _reconstructPacket(data[key], buffers);
                    }
                }

                return data;
            }

            /**
             * Asynchronously removes Blobs or Files from data via
             * FileReader's readAsArrayBuffer method. Used before encoding
             * data as msgpack. Calls callback with the blobless data.
             *
             * @param {Object} data
             * @param {Function} callback
             * @api private
             */

            exports.removeBlobs = function(data, callback) {
                function _removeBlobs(obj, curKey, containingObject) {
                    if (!obj) return obj;

                    // convert any blob
                    if ((withNativeBlob && obj instanceof Blob) ||
                        (withNativeFile && obj instanceof File)) {
                        pendingBlobs++;

                        // async filereader
                        var fileReader = new FileReader();
                        fileReader.onload = function() { // this.result == arraybuffer
                            if (containingObject) {
                                containingObject[curKey] = this.result;
                            }
                            else {
                                bloblessData = this.result;
                            }

                            // if nothing pending its callback time
                            if(! --pendingBlobs) {
                                callback(bloblessData);
                            }
                        };

                        fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
                    } else if (isArray(obj)) { // handle array
                        for (var i = 0; i < obj.length; i++) {
                            _removeBlobs(obj[i], i, obj);
                        }
                    } else if (typeof obj === 'object' && !isBuf(obj)) { // and object
                        for (var key in obj) {
                            _removeBlobs(obj[key], key, obj);
                        }
                    }
                }

                var pendingBlobs = 0;
                var bloblessData = data;
                _removeBlobs(bloblessData);
                if (!pendingBlobs) {
                    callback(bloblessData);
                }
            };

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"./is-buffer":59,"isarray":39}],58:[function(require,module,exports){

        /**
         * Module dependencies.
         */

        var debug = require('debug')('socket.io-parser');
        var Emitter = require('component-emitter');
        var hasBin = require('has-binary2');
        var binary = require('./binary');
        var isBuf = require('./is-buffer');

        /**
         * Protocol version.
         *
         * @api public
         */

        exports.protocol = 4;

        /**
         * Packet types.
         *
         * @api public
         */

        exports.types = [
            'CONNECT',
            'DISCONNECT',
            'EVENT',
            'ACK',
            'ERROR',
            'BINARY_EVENT',
            'BINARY_ACK'
        ];

        /**
         * Packet type `connect`.
         *
         * @api public
         */

        exports.CONNECT = 0;

        /**
         * Packet type `disconnect`.
         *
         * @api public
         */

        exports.DISCONNECT = 1;

        /**
         * Packet type `event`.
         *
         * @api public
         */

        exports.EVENT = 2;

        /**
         * Packet type `ack`.
         *
         * @api public
         */

        exports.ACK = 3;

        /**
         * Packet type `error`.
         *
         * @api public
         */

        exports.ERROR = 4;

        /**
         * Packet type 'binary event'
         *
         * @api public
         */

        exports.BINARY_EVENT = 5;

        /**
         * Packet type `binary ack`. For acks with binary arguments.
         *
         * @api public
         */

        exports.BINARY_ACK = 6;

        /**
         * Encoder constructor.
         *
         * @api public
         */

        exports.Encoder = Encoder;

        /**
         * Decoder constructor.
         *
         * @api public
         */

        exports.Decoder = Decoder;

        /**
         * A socket.io Encoder instance
         *
         * @api public
         */

        function Encoder() {}

        /**
         * Encode a packet as a single string if non-binary, or as a
         * buffer sequence, depending on packet type.
         *
         * @param {Object} obj - packet object
         * @param {Function} callback - function to handle encodings (likely engine.write)
         * @return Calls callback with Array of encodings
         * @api public
         */

        Encoder.prototype.encode = function(obj, callback){
            if ((obj.type === exports.EVENT || obj.type === exports.ACK) && hasBin(obj.data)) {
                obj.type = obj.type === exports.EVENT ? exports.BINARY_EVENT : exports.BINARY_ACK;
            }

            debug('encoding packet %j', obj);

            if (exports.BINARY_EVENT === obj.type || exports.BINARY_ACK === obj.type) {
                encodeAsBinary(obj, callback);
            }
            else {
                var encoding = encodeAsString(obj);
                callback([encoding]);
            }
        };

        /**
         * Encode packet as string.
         *
         * @param {Object} packet
         * @return {String} encoded
         * @api private
         */

        function encodeAsString(obj) {

            // first is type
            var str = '' + obj.type;

            // attachments if we have them
            if (exports.BINARY_EVENT === obj.type || exports.BINARY_ACK === obj.type) {
                str += obj.attachments + '-';
            }

            // if we have a namespace other than `/`
            // we append it followed by a comma `,`
            if (obj.nsp && '/' !== obj.nsp) {
                str += obj.nsp + ',';
            }

            // immediately followed by the id
            if (null != obj.id) {
                str += obj.id;
            }

            // json data
            if (null != obj.data) {
                str += JSON.stringify(obj.data);
            }

            debug('encoded %j as %s', obj, str);
            return str;
        }

        /**
         * Encode packet as 'buffer sequence' by removing blobs, and
         * deconstructing packet into object with placeholders and
         * a list of buffers.
         *
         * @param {Object} packet
         * @return {Buffer} encoded
         * @api private
         */

        function encodeAsBinary(obj, callback) {

            function writeEncoding(bloblessData) {
                var deconstruction = binary.deconstructPacket(bloblessData);
                var pack = encodeAsString(deconstruction.packet);
                var buffers = deconstruction.buffers;

                buffers.unshift(pack); // add packet info to beginning of data list
                callback(buffers); // write all the buffers
            }

            binary.removeBlobs(obj, writeEncoding);
        }

        /**
         * A socket.io Decoder instance
         *
         * @return {Object} decoder
         * @api public
         */

        function Decoder() {
            this.reconstructor = null;
        }

        /**
         * Mix in `Emitter` with Decoder.
         */

        Emitter(Decoder.prototype);

        /**
         * Decodes an ecoded packet string into packet JSON.
         *
         * @param {String} obj - encoded packet
         * @return {Object} packet
         * @api public
         */

        Decoder.prototype.add = function(obj) {
            var packet;
            if (typeof obj === 'string') {
                packet = decodeString(obj);
                if (exports.BINARY_EVENT === packet.type || exports.BINARY_ACK === packet.type) { // binary packet's json
                    this.reconstructor = new BinaryReconstructor(packet);

                    // no attachments, labeled binary but no binary data to follow
                    if (this.reconstructor.reconPack.attachments === 0) {
                        this.emit('decoded', packet);
                    }
                } else { // non-binary full packet
                    this.emit('decoded', packet);
                }
            }
            else if (isBuf(obj) || obj.base64) { // raw binary data
                if (!this.reconstructor) {
                    throw new Error('got binary data when not reconstructing a packet');
                } else {
                    packet = this.reconstructor.takeBinaryData(obj);
                    if (packet) { // received final buffer
                        this.reconstructor = null;
                        this.emit('decoded', packet);
                    }
                }
            }
            else {
                throw new Error('Unknown type: ' + obj);
            }
        };

        /**
         * Decode a packet String (JSON data)
         *
         * @param {String} str
         * @return {Object} packet
         * @api private
         */

        function decodeString(str) {
            var i = 0;
            // look up type
            var p = {
                type: Number(str.charAt(0))
            };

            if (null == exports.types[p.type]) return error();

            // look up attachments if type binary
            if (exports.BINARY_EVENT === p.type || exports.BINARY_ACK === p.type) {
                var buf = '';
                while (str.charAt(++i) !== '-') {
                    buf += str.charAt(i);
                    if (i == str.length) break;
                }
                if (buf != Number(buf) || str.charAt(i) !== '-') {
                    throw new Error('Illegal attachments');
                }
                p.attachments = Number(buf);
            }

            // look up namespace (if any)
            if ('/' === str.charAt(i + 1)) {
                p.nsp = '';
                while (++i) {
                    var c = str.charAt(i);
                    if (',' === c) break;
                    p.nsp += c;
                    if (i === str.length) break;
                }
            } else {
                p.nsp = '/';
            }

            // look up id
            var next = str.charAt(i + 1);
            if ('' !== next && Number(next) == next) {
                p.id = '';
                while (++i) {
                    var c = str.charAt(i);
                    if (null == c || Number(c) != c) {
                        --i;
                        break;
                    }
                    p.id += str.charAt(i);
                    if (i === str.length) break;
                }
                p.id = Number(p.id);
            }

            // look up json data
            if (str.charAt(++i)) {
                p = tryParse(p, str.substr(i));
            }

            debug('decoded %s as %j', str, p);
            return p;
        }

        function tryParse(p, str) {
            try {
                p.data = JSON.parse(str);
            } catch(e){
                return error();
            }
            return p;
        }

        /**
         * Deallocates a parser's resources
         *
         * @api public
         */

        Decoder.prototype.destroy = function() {
            if (this.reconstructor) {
                this.reconstructor.finishedReconstruction();
            }
        };

        /**
         * A manager of a binary event's 'buffer sequence'. Should
         * be constructed whenever a packet of type BINARY_EVENT is
         * decoded.
         *
         * @param {Object} packet
         * @return {BinaryReconstructor} initialized reconstructor
         * @api private
         */

        function BinaryReconstructor(packet) {
            this.reconPack = packet;
            this.buffers = [];
        }

        /**
         * Method to be called when binary data received from connection
         * after a BINARY_EVENT packet.
         *
         * @param {Buffer | ArrayBuffer} binData - the raw binary data received
         * @return {null | Object} returns null if more binary data is expected or
         *   a reconstructed packet object if all buffers have been received.
         * @api private
         */

        BinaryReconstructor.prototype.takeBinaryData = function(binData) {
            this.buffers.push(binData);
            if (this.buffers.length === this.reconPack.attachments) { // done with buffer list
                var packet = binary.reconstructPacket(this.reconPack, this.buffers);
                this.finishedReconstruction();
                return packet;
            }
            return null;
        };

        /**
         * Cleans up binary packet reconstruction variables.
         *
         * @api private
         */

        BinaryReconstructor.prototype.finishedReconstruction = function() {
            this.reconPack = null;
            this.buffers = [];
        };

        function error() {
            return {
                type: exports.ERROR,
                data: 'parser error'
            };
        }

    },{"./binary":57,"./is-buffer":59,"component-emitter":9,"debug":14,"has-binary2":36}],59:[function(require,module,exports){
        (function (global){

            module.exports = isBuf;

            /**
             * Returns true if obj is a buffer or an arraybuffer.
             *
             * @api private
             */

            function isBuf(obj) {
                return (global.Buffer && global.Buffer.isBuffer(obj)) ||
                    (global.ArrayBuffer && obj instanceof ArrayBuffer);
            }

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{}],60:[function(require,module,exports){
        module.exports = toArray

        function toArray(list, index) {
            var array = []

            index = index || 0

            for (var i = index || 0; i < list.length; i++) {
                array[i - index] = list[i]
            }

            return array
        }

    },{}],61:[function(require,module,exports){
// Generated by Babel
        "use strict";

        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        exports.encode = encode;
        /* global: window */

        var _window = window;
        var btoa = _window.btoa;
        function encode(data) {
            return btoa(unescape(encodeURIComponent(data)));
        }

        var isSupported = exports.isSupported = "btoa" in window;
    },{}],62:[function(require,module,exports){
// Generated by Babel
        "use strict";

        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        exports.newRequest = newRequest;
        exports.resolveUrl = resolveUrl;

        var _resolveUrl = require("resolve-url");

        var _resolveUrl2 = _interopRequireDefault(_resolveUrl);

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

        function newRequest() {
            return new window.XMLHttpRequest();
        } /* global window */


        function resolveUrl(origin, link) {
            return (0, _resolveUrl2.default)(origin, link);
        }
    },{"resolve-url":50}],63:[function(require,module,exports){
// Generated by Babel
        "use strict";

        var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        exports.getSource = getSource;

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var FileSource = function () {
            function FileSource(file) {
                _classCallCheck(this, FileSource);

                this._file = file;
                this.size = file.size;
            }

            _createClass(FileSource, [{
                key: "slice",
                value: function slice(start, end) {
                    return this._file.slice(start, end);
                }
            }, {
                key: "close",
                value: function close() {}
            }]);

            return FileSource;
        }();

        function getSource(input) {
            // Since we emulate the Blob type in our tests (not all target browsers
            // support it), we cannot use `instanceof` for testing whether the input value
            // can be handled. Instead, we simply check is the slice() function and the
            // size property are available.
            if (typeof input.slice === "function" && typeof input.size !== "undefined") {
                return new FileSource(input);
            }

            throw new Error("source object may only be an instance of File or Blob in this environment");
        }
    },{}],64:[function(require,module,exports){
// Generated by Babel
        "use strict";

        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        exports.setItem = setItem;
        exports.getItem = getItem;
        exports.removeItem = removeItem;
        /* global window, localStorage */

        var hasStorage = false;
        try {
            hasStorage = "localStorage" in window;

            // Attempt to store and read entries from the local storage to detect Private
            // Mode on Safari on iOS (see #49)
            var key = "tusSupport";
            localStorage.setItem(key, localStorage.getItem(key));
        } catch (e) {
            // If we try to access localStorage inside a sandboxed iframe, a SecurityError
            // is thrown. When in private mode on iOS Safari, a QuotaExceededError is
            // thrown (see #49)
            if (e.code === e.SECURITY_ERR || e.code === e.QUOTA_EXCEEDED_ERR) {
                hasStorage = false;
            } else {
                throw e;
            }
        }

        var canStoreURLs = exports.canStoreURLs = hasStorage;

        function setItem(key, value) {
            if (!hasStorage) return;
            return localStorage.setItem(key, value);
        }

        function getItem(key) {
            if (!hasStorage) return;
            return localStorage.getItem(key);
        }

        function removeItem(key) {
            if (!hasStorage) return;
            return localStorage.removeItem(key);
        }
    },{}],65:[function(require,module,exports){
// Generated by Babel
        "use strict";

        Object.defineProperty(exports, "__esModule", {
            value: true
        });

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var DetailedError = function (_Error) {
            _inherits(DetailedError, _Error);

            function DetailedError(error) {
                var causingErr = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];
                var xhr = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];

                _classCallCheck(this, DetailedError);

                var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(DetailedError).call(this, error.message));

                _this.originalRequest = xhr;
                _this.causingError = causingErr;

                var message = error.message;
                if (causingErr != null) {
                    message += ", caused by " + causingErr.toString();
                }
                if (xhr != null) {
                    message += ", originated from request (response code: " + xhr.status + ", response text: " + xhr.responseText + ")";
                }
                _this.message = message;
                return _this;
            }

            return DetailedError;
        }(Error);

        exports.default = DetailedError;
    },{}],66:[function(require,module,exports){
// Generated by Babel
        "use strict";

        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        exports.default = fingerprint;
        /**
         * Generate a fingerprint for a file which will be used the store the endpoint
         *
         * @param {File} file
         * @return {String}
         */
        function fingerprint(file) {
            return ["tus", file.name, file.type, file.size, file.lastModified].join("-");
        }
    },{}],67:[function(require,module,exports){
// Generated by Babel
        "use strict";

        var _upload = require("./upload");

        var _upload2 = _interopRequireDefault(_upload);

        var _storage = require("./node/storage");

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

        /* global window */
        var defaultOptions = _upload2.default.defaultOptions;


        if (typeof window !== "undefined") {
            // Browser environment using XMLHttpRequest
            var _window = window;
            var XMLHttpRequest = _window.XMLHttpRequest;
            var Blob = _window.Blob;


            var isSupported = XMLHttpRequest && Blob && typeof Blob.prototype.slice === "function";
        } else {
            // Node.js environment using http module
            var isSupported = true;
        }

// The usage of the commonjs exporting syntax instead of the new ECMAScript
// one is actually inteded and prevents weird behaviour if we are trying to
// import this module in another module using Babel.
        module.exports = {
            Upload: _upload2.default,
            isSupported: isSupported,
            canStoreURLs: _storage.canStoreURLs,
            defaultOptions: defaultOptions
        };
    },{"./node/storage":64,"./upload":68}],68:[function(require,module,exports){
// Generated by Babel
        "use strict";

        var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* global window */


// We import the files used inside the Node environment which are rewritten
// for browsers using the rules defined in the package.json


        Object.defineProperty(exports, "__esModule", {
            value: true
        });

        var _fingerprint = require("./fingerprint");

        var _fingerprint2 = _interopRequireDefault(_fingerprint);

        var _error = require("./error");

        var _error2 = _interopRequireDefault(_error);

        var _extend = require("extend");

        var _extend2 = _interopRequireDefault(_extend);

        var _request = require("./node/request");

        var _source = require("./node/source");

        var _base = require("./node/base64");

        var Base64 = _interopRequireWildcard(_base);

        var _storage = require("./node/storage");

        var Storage = _interopRequireWildcard(_storage);

        function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

        function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var defaultOptions = {
            endpoint: "",
            fingerprint: _fingerprint2.default,
            resume: true,
            onProgress: null,
            onChunkComplete: null,
            onSuccess: null,
            onError: null,
            headers: {},
            chunkSize: Infinity,
            withCredentials: false,
            uploadUrl: null,
            uploadSize: null,
            overridePatchMethod: false,
            retryDelays: null
        };

        var Upload = function () {
            function Upload(file, options) {
                _classCallCheck(this, Upload);

                this.options = (0, _extend2.default)(true, {}, defaultOptions, options);

                // The underlying File/Blob object
                this.file = file;

                // The URL against which the file will be uploaded
                this.url = null;

                // The underlying XHR object for the current PATCH request
                this._xhr = null;

                // The fingerpinrt for the current file (set after start())
                this._fingerprint = null;

                // The offset used in the current PATCH request
                this._offset = null;

                // True if the current PATCH request has been aborted
                this._aborted = false;

                // The file's size in bytes
                this._size = null;

                // The Source object which will wrap around the given file and provides us
                // with a unified interface for getting its size and slice chunks from its
                // content allowing us to easily handle Files, Blobs, Buffers and Streams.
                this._source = null;

                // The current count of attempts which have been made. Null indicates none.
                this._retryAttempt = 0;

                // The timeout's ID which is used to delay the next retry
                this._retryTimeout = null;

                // The offset of the remote upload before the latest attempt was started.
                this._offsetBeforeRetry = 0;
            }

            _createClass(Upload, [{
                key: "start",
                value: function start() {
                    var _this = this;

                    var file = this.file;

                    if (!file) {
                        this._emitError(new Error("tus: no file or stream to upload provided"));
                        return;
                    }

                    if (!this.options.endpoint) {
                        this._emitError(new Error("tus: no endpoint provided"));
                        return;
                    }

                    var source = this._source = (0, _source.getSource)(file, this.options.chunkSize);

                    // Firstly, check if the caller has supplied a manual upload size or else
                    // we will use the calculated size by the source object.
                    if (this.options.uploadSize != null) {
                        var size = +this.options.uploadSize;
                        if (isNaN(size)) {
                            throw new Error("tus: cannot convert `uploadSize` option into a number");
                        }

                        this._size = size;
                    } else {
                        var size = source.size;

                        // The size property will be null if we cannot calculate the file's size,
                        // for example if you handle a stream.
                        if (size == null) {
                            throw new Error("tus: cannot automatically derive upload's size from input and must be specified manually using the `uploadSize` option");
                        }

                        this._size = size;
                    }

                    var retryDelays = this.options.retryDelays;
                    if (retryDelays != null) {
                        if (Object.prototype.toString.call(retryDelays) !== "[object Array]") {
                            throw new Error("tus: the `retryDelays` option must either be an array or null");
                        } else {
                            (function () {
                                var errorCallback = _this.options.onError;
                                _this.options.onError = function (err) {
                                    // Restore the original error callback which may have been set.
                                    _this.options.onError = errorCallback;

                                    // We will reset the attempt counter if
                                    // - we were already able to connect to the server (offset != null) and
                                    // - we were able to upload a small chunk of data to the server
                                    var shouldResetDelays = _this._offset != null && _this._offset > _this._offsetBeforeRetry;
                                    if (shouldResetDelays) {
                                        _this._retryAttempt = 0;
                                    }

                                    var isOnline = true;
                                    if (typeof window !== "undefined" && "navigator" in window && window.navigator.onLine === false) {
                                        isOnline = false;
                                    }

                                    // We only attempt a retry if
                                    // - we didn't exceed the maxium number of retries, yet, and
                                    // - this error was caused by a request or it's response and
                                    // - the error is not a client error (status 4xx) and
                                    // - the browser does not indicate that we are offline
                                    var shouldRetry = _this._retryAttempt < retryDelays.length && err.originalRequest != null && !inStatusCategory(err.originalRequest.status, 400) && isOnline;

                                    if (!shouldRetry) {
                                        _this._emitError(err);
                                        return;
                                    }

                                    var delay = retryDelays[_this._retryAttempt++];

                                    _this._offsetBeforeRetry = _this._offset;
                                    _this.options.uploadUrl = _this.url;

                                    _this._retryTimeout = setTimeout(function () {
                                        _this.start();
                                    }, delay);
                                };
                            })();
                        }
                    }

                    // Reset the aborted flag when the upload is started or else the
                    // _startUpload will stop before sending a request if the upload has been
                    // aborted previously.
                    this._aborted = false;

                    // The upload had been started previously and we should reuse this URL.
                    if (this.url != null) {
                        this._resumeUpload();
                        return;
                    }

                    // A URL has manually been specified, so we try to resume
                    if (this.options.uploadUrl != null) {
                        this.url = this.options.uploadUrl;
                        this._resumeUpload();
                        return;
                    }

                    // Try to find the endpoint for the file in the storage
                    if (this.options.resume) {
                        this._fingerprint = this.options.fingerprint(file);
                        var resumedUrl = Storage.getItem(this._fingerprint);

                        if (resumedUrl != null) {
                            this.url = resumedUrl;
                            this._resumeUpload();
                            return;
                        }
                    }

                    // An upload has not started for the file yet, so we start a new one
                    this._createUpload();
                }
            }, {
                key: "abort",
                value: function abort() {
                    if (this._xhr !== null) {
                        this._xhr.abort();
                        this._source.close();
                        this._aborted = true;
                    }

                    if (this._retryTimeout != null) {
                        clearTimeout(this._retryTimeout);
                        this._retryTimeout = null;
                    }
                }
            }, {
                key: "_emitXhrError",
                value: function _emitXhrError(xhr, err, causingErr) {
                    this._emitError(new _error2.default(err, causingErr, xhr));
                }
            }, {
                key: "_emitError",
                value: function _emitError(err) {
                    if (typeof this.options.onError === "function") {
                        this.options.onError(err);
                    } else {
                        throw err;
                    }
                }
            }, {
                key: "_emitSuccess",
                value: function _emitSuccess() {
                    if (typeof this.options.onSuccess === "function") {
                        this.options.onSuccess();
                    }
                }

                /**
                 * Publishes notification when data has been sent to the server. This
                 * data may not have been accepted by the server yet.
                 * @param  {number} bytesSent  Number of bytes sent to the server.
                 * @param  {number} bytesTotal Total number of bytes to be sent to the server.
                 */

            }, {
                key: "_emitProgress",
                value: function _emitProgress(bytesSent, bytesTotal) {
                    if (typeof this.options.onProgress === "function") {
                        this.options.onProgress(bytesSent, bytesTotal);
                    }
                }

                /**
                 * Publishes notification when a chunk of data has been sent to the server
                 * and accepted by the server.
                 * @param  {number} chunkSize  Size of the chunk that was accepted by the
                 *                             server.
                 * @param  {number} bytesAccepted Total number of bytes that have been
                 *                                accepted by the server.
                 * @param  {number} bytesTotal Total number of bytes to be sent to the server.
                 */

            }, {
                key: "_emitChunkComplete",
                value: function _emitChunkComplete(chunkSize, bytesAccepted, bytesTotal) {
                    if (typeof this.options.onChunkComplete === "function") {
                        this.options.onChunkComplete(chunkSize, bytesAccepted, bytesTotal);
                    }
                }

                /**
                 * Set the headers used in the request and the withCredentials property
                 * as defined in the options
                 *
                 * @param {XMLHttpRequest} xhr
                 */

            }, {
                key: "_setupXHR",
                value: function _setupXHR(xhr) {
                    this._xhr = xhr;

                    xhr.setRequestHeader("Tus-Resumable", "1.0.0");
                    var headers = this.options.headers;

                    for (var name in headers) {
                        xhr.setRequestHeader(name, headers[name]);
                    }

                    xhr.withCredentials = this.options.withCredentials;
                }

                /**
                 * Create a new upload using the creation extension by sending a POST
                 * request to the endpoint. After successful creation the file will be
                 * uploaded
                 *
                 * @api private
                 */

            }, {
                key: "_createUpload",
                value: function _createUpload() {
                    var _this2 = this;

                    var xhr = (0, _request.newRequest)();
                    xhr.open("POST", this.options.endpoint, true);

                    xhr.onload = function () {
                        if (!inStatusCategory(xhr.status, 200)) {
                            _this2._emitXhrError(xhr, new Error("tus: unexpected response while creating upload"));
                            return;
                        }

                        var location = xhr.getResponseHeader("Location");
                        if (location == null) {
                            _this2._emitXhrError(xhr, new Error("tus: invalid or missing Location header"));
                            return;
                        }

                        _this2.url = (0, _request.resolveUrl)(_this2.options.endpoint, location);

                        if (_this2.options.resume) {
                            Storage.setItem(_this2._fingerprint, _this2.url);
                        }

                        _this2._offset = 0;
                        _this2._startUpload();
                    };

                    xhr.onerror = function (err) {
                        _this2._emitXhrError(xhr, new Error("tus: failed to create upload"), err);
                    };

                    this._setupXHR(xhr);
                    xhr.setRequestHeader("Upload-Length", this._size);

                    // Add metadata if values have been added
                    var metadata = encodeMetadata(this.options.metadata);
                    if (metadata !== "") {
                        xhr.setRequestHeader("Upload-Metadata", metadata);
                    }

                    xhr.send(null);
                }

                /*
     * Try to resume an existing upload. First a HEAD request will be sent
     * to retrieve the offset. If the request fails a new upload will be
     * created. In the case of a successful response the file will be uploaded.
     *
     * @api private
     */

            }, {
                key: "_resumeUpload",
                value: function _resumeUpload() {
                    var _this3 = this;

                    var xhr = (0, _request.newRequest)();
                    xhr.open("HEAD", this.url, true);

                    xhr.onload = function () {
                        if (!inStatusCategory(xhr.status, 200)) {
                            if (_this3.options.resume && inStatusCategory(xhr.status, 400)) {
                                // Remove stored fingerprint and corresponding endpoint,
                                // on client errors since the file can not be found
                                Storage.removeItem(_this3._fingerprint);
                            }

                            // If the upload is locked (indicated by the 423 Locked status code), we
                            // emit an error instead of directly starting a new upload. This way the
                            // retry logic can catch the error and will retry the upload. An upload
                            // is usually locked for a short period of time and will be available
                            // afterwards.
                            if (xhr.status === 423) {
                                _this3._emitXhrError(xhr, new Error("tus: upload is currently locked; retry later"));
                                return;
                            }

                            // Try to create a new upload
                            _this3.url = null;
                            _this3._createUpload();
                            return;
                        }

                        var offset = parseInt(xhr.getResponseHeader("Upload-Offset"), 10);
                        if (isNaN(offset)) {
                            _this3._emitXhrError(xhr, new Error("tus: invalid or missing offset value"));
                            return;
                        }

                        var length = parseInt(xhr.getResponseHeader("Upload-Length"), 10);
                        if (isNaN(length)) {
                            _this3._emitXhrError(xhr, new Error("tus: invalid or missing length value"));
                            return;
                        }

                        // Upload has already been completed and we do not need to send additional
                        // data to the server
                        if (offset === length) {
                            _this3._emitProgress(length, length);
                            _this3._emitSuccess();
                            return;
                        }

                        _this3._offset = offset;
                        _this3._startUpload();
                    };

                    xhr.onerror = function (err) {
                        _this3._emitXhrError(xhr, new Error("tus: failed to resume upload"), err);
                    };

                    this._setupXHR(xhr);
                    xhr.send(null);
                }

                /**
                 * Start uploading the file using PATCH requests. The file will be divided
                 * into chunks as specified in the chunkSize option. During the upload
                 * the onProgress event handler may be invoked multiple times.
                 *
                 * @api private
                 */

            }, {
                key: "_startUpload",
                value: function _startUpload() {
                    var _this4 = this;

                    // If the upload has been aborted, we will not send the next PATCH request.
                    // This is important if the abort method was called during a callback, such
                    // as onChunkComplete or onProgress.
                    if (this._aborted) {
                        return;
                    }

                    var xhr = (0, _request.newRequest)();

                    // Some browser and servers may not support the PATCH method. For those
                    // cases, you can tell tus-js-client to use a POST request with the
                    // X-HTTP-Method-Override header for simulating a PATCH request.
                    if (this.options.overridePatchMethod) {
                        xhr.open("POST", this.url, true);
                        xhr.setRequestHeader("X-HTTP-Method-Override", "PATCH");
                    } else {
                        xhr.open("PATCH", this.url, true);
                    }

                    xhr.onload = function () {
                        if (!inStatusCategory(xhr.status, 200)) {
                            _this4._emitXhrError(xhr, new Error("tus: unexpected response while uploading chunk"));
                            return;
                        }

                        var offset = parseInt(xhr.getResponseHeader("Upload-Offset"), 10);
                        if (isNaN(offset)) {
                            _this4._emitXhrError(xhr, new Error("tus: invalid or missing offset value"));
                            return;
                        }

                        _this4._emitProgress(offset, _this4._size);
                        _this4._emitChunkComplete(offset - _this4._offset, offset, _this4._size);

                        _this4._offset = offset;

                        if (offset == _this4._size) {
                            // Yay, finally done :)
                            _this4._emitSuccess();
                            _this4._source.close();
                            return;
                        }

                        _this4._startUpload();
                    };

                    xhr.onerror = function (err) {
                        // Don't emit an error if the upload was aborted manually
                        if (_this4._aborted) {
                            return;
                        }

                        _this4._emitXhrError(xhr, new Error("tus: failed to upload chunk at offset " + _this4._offset), err);
                    };

                    // Test support for progress events before attaching an event listener
                    if ("upload" in xhr) {
                        xhr.upload.onprogress = function (e) {
                            if (!e.lengthComputable) {
                                return;
                            }

                            _this4._emitProgress(start + e.loaded, _this4._size);
                        };
                    }

                    this._setupXHR(xhr);

                    xhr.setRequestHeader("Upload-Offset", this._offset);
                    xhr.setRequestHeader("Content-Type", "application/offset+octet-stream");

                    var start = this._offset;
                    var end = this._offset + this.options.chunkSize;

                    // The specified chunkSize may be Infinity or the calcluated end position
                    // may exceed the file's size. In both cases, we limit the end position to
                    // the input's total size for simpler calculations and correctness.
                    if (end === Infinity || end > this._size) {
                        end = this._size;
                    }

                    xhr.send(this._source.slice(start, end));

                    // Emit an progress event when a new chunk begins being uploaded.
                    this._emitProgress(this._offset, this._size);
                }
            }]);

            return Upload;
        }();

        function encodeMetadata(metadata) {
            if (!Base64.isSupported) {
                return "";
            }

            var encoded = [];

            for (var key in metadata) {
                encoded.push(key + " " + Base64.encode(metadata[key]));
            }

            return encoded.join(",");
        }

        /**
         * Checks whether a given status is in the range of the expected category.
         * For example, only a status between 200 and 299 will satisfy the category 200.
         *
         * @api private
         */
        function inStatusCategory(status, category) {
            return status >= category && status < category + 100;
        }

        Upload.defaultOptions = defaultOptions;

        exports.default = Upload;
    },{"./error":65,"./fingerprint":66,"./node/base64":61,"./node/request":62,"./node/source":63,"./node/storage":64,"extend":34}],69:[function(require,module,exports){
        (function (global){
            'use strict';

            var required = require('requires-port')
                , qs = require('querystringify')
                , protocolre = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i
                , slashes = /^[A-Za-z][A-Za-z0-9+-.]*:\/\//;

            /**
             * These are the parse rules for the URL parser, it informs the parser
             * about:
             *
             * 0. The char it Needs to parse, if it's a string it should be done using
             *    indexOf, RegExp using exec and NaN means set as current value.
             * 1. The property we should set when parsing this value.
             * 2. Indication if it's backwards or forward parsing, when set as number it's
             *    the value of extra chars that should be split off.
             * 3. Inherit from location if non existing in the parser.
             * 4. `toLowerCase` the resulting value.
             */
            var rules = [
                ['#', 'hash'],                        // Extract from the back.
                ['?', 'query'],                       // Extract from the back.
                ['/', 'pathname'],                    // Extract from the back.
                ['@', 'auth', 1],                     // Extract from the front.
                [NaN, 'host', undefined, 1, 1],       // Set left over value.
                [/:(\d+)$/, 'port', undefined, 1],    // RegExp the back.
                [NaN, 'hostname', undefined, 1, 1]    // Set left over.
            ];

            /**
             * These properties should not be copied or inherited from. This is only needed
             * for all non blob URL's as a blob URL does not include a hash, only the
             * origin.
             *
             * @type {Object}
             * @private
             */
            var ignore = { hash: 1, query: 1 };

            /**
             * The location object differs when your code is loaded through a normal page,
             * Worker or through a worker using a blob. And with the blobble begins the
             * trouble as the location object will contain the URL of the blob, not the
             * location of the page where our code is loaded in. The actual origin is
             * encoded in the `pathname` so we can thankfully generate a good "default"
             * location from it so we can generate proper relative URL's again.
             *
             * @param {Object|String} loc Optional default location object.
             * @returns {Object} lolcation object.
             * @api public
             */
            function lolcation(loc) {
                loc = loc || global.location || {};

                var finaldestination = {}
                    , type = typeof loc
                    , key;

                if ('blob:' === loc.protocol) {
                    finaldestination = new URL(unescape(loc.pathname), {});
                } else if ('string' === type) {
                    finaldestination = new URL(loc, {});
                    for (key in ignore) delete finaldestination[key];
                } else if ('object' === type) {
                    for (key in loc) {
                        if (key in ignore) continue;
                        finaldestination[key] = loc[key];
                    }

                    if (finaldestination.slashes === undefined) {
                        finaldestination.slashes = slashes.test(loc.href);
                    }
                }

                return finaldestination;
            }

            /**
             * @typedef ProtocolExtract
             * @type Object
             * @property {String} protocol Protocol matched in the URL, in lowercase.
             * @property {Boolean} slashes `true` if protocol is followed by "//", else `false`.
             * @property {String} rest Rest of the URL that is not part of the protocol.
             */

            /**
             * Extract protocol information from a URL with/without double slash ("//").
             *
             * @param {String} address URL we want to extract from.
             * @return {ProtocolExtract} Extracted information.
             * @api private
             */
            function extractProtocol(address) {
                var match = protocolre.exec(address);

                return {
                    protocol: match[1] ? match[1].toLowerCase() : '',
                    slashes: !!match[2],
                    rest: match[3]
                };
            }

            /**
             * Resolve a relative URL pathname against a base URL pathname.
             *
             * @param {String} relative Pathname of the relative URL.
             * @param {String} base Pathname of the base URL.
             * @return {String} Resolved pathname.
             * @api private
             */
            function resolve(relative, base) {
                var path = (base || '/').split('/').slice(0, -1).concat(relative.split('/'))
                    , i = path.length
                    , last = path[i - 1]
                    , unshift = false
                    , up = 0;

                while (i--) {
                    if (path[i] === '.') {
                        path.splice(i, 1);
                    } else if (path[i] === '..') {
                        path.splice(i, 1);
                        up++;
                    } else if (up) {
                        if (i === 0) unshift = true;
                        path.splice(i, 1);
                        up--;
                    }
                }

                if (unshift) path.unshift('');
                if (last === '.' || last === '..') path.push('');

                return path.join('/');
            }

            /**
             * The actual URL instance. Instead of returning an object we've opted-in to
             * create an actual constructor as it's much more memory efficient and
             * faster and it pleases my OCD.
             *
             * @constructor
             * @param {String} address URL we want to parse.
             * @param {Object|String} location Location defaults for relative paths.
             * @param {Boolean|Function} parser Parser for the query string.
             * @api public
             */
            function URL(address, location, parser) {
                if (!(this instanceof URL)) {
                    return new URL(address, location, parser);
                }

                var relative, extracted, parse, instruction, index, key
                    , instructions = rules.slice()
                    , type = typeof location
                    , url = this
                    , i = 0;

                //
                // The following if statements allows this module two have compatibility with
                // 2 different API:
                //
                // 1. Node.js's `url.parse` api which accepts a URL, boolean as arguments
                //    where the boolean indicates that the query string should also be parsed.
                //
                // 2. The `URL` interface of the browser which accepts a URL, object as
                //    arguments. The supplied object will be used as default values / fall-back
                //    for relative paths.
                //
                if ('object' !== type && 'string' !== type) {
                    parser = location;
                    location = null;
                }

                if (parser && 'function' !== typeof parser) parser = qs.parse;

                location = lolcation(location);

                //
                // Extract protocol information before running the instructions.
                //
                extracted = extractProtocol(address || '');
                relative = !extracted.protocol && !extracted.slashes;
                url.slashes = extracted.slashes || relative && location.slashes;
                url.protocol = extracted.protocol || location.protocol || '';
                address = extracted.rest;

                //
                // When the authority component is absent the URL starts with a path
                // component.
                //
                if (!extracted.slashes) instructions[2] = [/(.*)/, 'pathname'];

                for (; i < instructions.length; i++) {
                    instruction = instructions[i];
                    parse = instruction[0];
                    key = instruction[1];

                    if (parse !== parse) {
                        url[key] = address;
                    } else if ('string' === typeof parse) {
                        if (~(index = address.indexOf(parse))) {
                            if ('number' === typeof instruction[2]) {
                                url[key] = address.slice(0, index);
                                address = address.slice(index + instruction[2]);
                            } else {
                                url[key] = address.slice(index);
                                address = address.slice(0, index);
                            }
                        }
                    } else if ((index = parse.exec(address))) {
                        url[key] = index[1];
                        address = address.slice(0, index.index);
                    }

                    url[key] = url[key] || (
                        relative && instruction[3] ? location[key] || '' : ''
                    );

                    //
                    // Hostname, host and protocol should be lowercased so they can be used to
                    // create a proper `origin`.
                    //
                    if (instruction[4]) url[key] = url[key].toLowerCase();
                }

                //
                // Also parse the supplied query string in to an object. If we're supplied
                // with a custom parser as function use that instead of the default build-in
                // parser.
                //
                if (parser) url.query = parser(url.query);

                //
                // If the URL is relative, resolve the pathname against the base URL.
                //
                if (
                    relative
                    && location.slashes
                    && url.pathname.charAt(0) !== '/'
                    && (url.pathname !== '' || location.pathname !== '')
                ) {
                    url.pathname = resolve(url.pathname, location.pathname);
                }

                //
                // We should not add port numbers if they are already the default port number
                // for a given protocol. As the host also contains the port number we're going
                // override it with the hostname which contains no port number.
                //
                if (!required(url.port, url.protocol)) {
                    url.host = url.hostname;
                    url.port = '';
                }

                //
                // Parse down the `auth` for the username and password.
                //
                url.username = url.password = '';
                if (url.auth) {
                    instruction = url.auth.split(':');
                    url.username = instruction[0] || '';
                    url.password = instruction[1] || '';
                }

                url.origin = url.protocol && url.host && url.protocol !== 'file:'
                    ? url.protocol +'//'+ url.host
                    : 'null';

                //
                // The href is just the compiled result.
                //
                url.href = url.toString();
            }

            /**
             * This is convenience method for changing properties in the URL instance to
             * insure that they all propagate correctly.
             *
             * @param {String} part          Property we need to adjust.
             * @param {Mixed} value          The newly assigned value.
             * @param {Boolean|Function} fn  When setting the query, it will be the function
             *                               used to parse the query.
             *                               When setting the protocol, double slash will be
             *                               removed from the final url if it is true.
             * @returns {URL}
             * @api public
             */
            function set(part, value, fn) {
                var url = this;

                switch (part) {
                    case 'query':
                        if ('string' === typeof value && value.length) {
                            value = (fn || qs.parse)(value);
                        }

                        url[part] = value;
                        break;

                    case 'port':
                        url[part] = value;

                        if (!required(value, url.protocol)) {
                            url.host = url.hostname;
                            url[part] = '';
                        } else if (value) {
                            url.host = url.hostname +':'+ value;
                        }

                        break;

                    case 'hostname':
                        url[part] = value;

                        if (url.port) value += ':'+ url.port;
                        url.host = value;
                        break;

                    case 'host':
                        url[part] = value;

                        if (/:\d+$/.test(value)) {
                            value = value.split(':');
                            url.port = value.pop();
                            url.hostname = value.join(':');
                        } else {
                            url.hostname = value;
                            url.port = '';
                        }

                        break;

                    case 'protocol':
                        url.protocol = value.toLowerCase();
                        url.slashes = !fn;
                        break;

                    case 'pathname':
                    case 'hash':
                        if (value) {
                            var char = part === 'pathname' ? '/' : '#';
                            url[part] = value.charAt(0) !== char ? char + value : value;
                        } else {
                            url[part] = value;
                        }
                        break;

                    default:
                        url[part] = value;
                }

                for (var i = 0; i < rules.length; i++) {
                    var ins = rules[i];

                    if (ins[4]) url[ins[1]] = url[ins[1]].toLowerCase();
                }

                url.origin = url.protocol && url.host && url.protocol !== 'file:'
                    ? url.protocol +'//'+ url.host
                    : 'null';

                url.href = url.toString();

                return url;
            }

            /**
             * Transform the properties back in to a valid and full URL string.
             *
             * @param {Function} stringify Optional query stringify function.
             * @returns {String}
             * @api public
             */
            function toString(stringify) {
                if (!stringify || 'function' !== typeof stringify) stringify = qs.stringify;

                var query
                    , url = this
                    , protocol = url.protocol;

                if (protocol && protocol.charAt(protocol.length - 1) !== ':') protocol += ':';

                var result = protocol + (url.slashes ? '//' : '');

                if (url.username) {
                    result += url.username;
                    if (url.password) result += ':'+ url.password;
                    result += '@';
                }

                result += url.host + url.pathname;

                query = 'object' === typeof url.query ? stringify(url.query) : url.query;
                if (query) result += '?' !== query.charAt(0) ? '?'+ query : query;

                if (url.hash) result += url.hash;

                return result;
            }

            URL.prototype = { set: set, toString: toString };

//
// Expose the URL parser and some additional properties that might be useful for
// others or testing.
//
            URL.extractProtocol = extractProtocol;
            URL.location = lolcation;
            URL.qs = qs;

            module.exports = URL;

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"querystringify":48,"requires-port":49}],70:[function(require,module,exports){
        (function(self) {
            'use strict';

            if (self.fetch) {
                return
            }

            var support = {
                searchParams: 'URLSearchParams' in self,
                iterable: 'Symbol' in self && 'iterator' in Symbol,
                blob: 'FileReader' in self && 'Blob' in self && (function() {
                    try {
                        new Blob()
                        return true
                    } catch(e) {
                        return false
                    }
                })(),
                formData: 'FormData' in self,
                arrayBuffer: 'ArrayBuffer' in self
            }

            if (support.arrayBuffer) {
                var viewClasses = [
                    '[object Int8Array]',
                    '[object Uint8Array]',
                    '[object Uint8ClampedArray]',
                    '[object Int16Array]',
                    '[object Uint16Array]',
                    '[object Int32Array]',
                    '[object Uint32Array]',
                    '[object Float32Array]',
                    '[object Float64Array]'
                ]

                var isDataView = function(obj) {
                    return obj && DataView.prototype.isPrototypeOf(obj)
                }

                var isArrayBufferView = ArrayBuffer.isView || function(obj) {
                    return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
                }
            }

            function normalizeName(name) {
                if (typeof name !== 'string') {
                    name = String(name)
                }
                if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
                    throw new TypeError('Invalid character in header field name')
                }
                return name.toLowerCase()
            }

            function normalizeValue(value) {
                if (typeof value !== 'string') {
                    value = String(value)
                }
                return value
            }

            // Build a destructive iterator for the value list
            function iteratorFor(items) {
                var iterator = {
                    next: function() {
                        var value = items.shift()
                        return {done: value === undefined, value: value}
                    }
                }

                if (support.iterable) {
                    iterator[Symbol.iterator] = function() {
                        return iterator
                    }
                }

                return iterator
            }

            function Headers(headers) {
                this.map = {}

                if (headers instanceof Headers) {
                    headers.forEach(function(value, name) {
                        this.append(name, value)
                    }, this)
                } else if (Array.isArray(headers)) {
                    headers.forEach(function(header) {
                        this.append(header[0], header[1])
                    }, this)
                } else if (headers) {
                    Object.getOwnPropertyNames(headers).forEach(function(name) {
                        this.append(name, headers[name])
                    }, this)
                }
            }

            Headers.prototype.append = function(name, value) {
                name = normalizeName(name)
                value = normalizeValue(value)
                var oldValue = this.map[name]
                this.map[name] = oldValue ? oldValue+','+value : value
            }

            Headers.prototype['delete'] = function(name) {
                delete this.map[normalizeName(name)]
            }

            Headers.prototype.get = function(name) {
                name = normalizeName(name)
                return this.has(name) ? this.map[name] : null
            }

            Headers.prototype.has = function(name) {
                return this.map.hasOwnProperty(normalizeName(name))
            }

            Headers.prototype.set = function(name, value) {
                this.map[normalizeName(name)] = normalizeValue(value)
            }

            Headers.prototype.forEach = function(callback, thisArg) {
                for (var name in this.map) {
                    if (this.map.hasOwnProperty(name)) {
                        callback.call(thisArg, this.map[name], name, this)
                    }
                }
            }

            Headers.prototype.keys = function() {
                var items = []
                this.forEach(function(value, name) { items.push(name) })
                return iteratorFor(items)
            }

            Headers.prototype.values = function() {
                var items = []
                this.forEach(function(value) { items.push(value) })
                return iteratorFor(items)
            }

            Headers.prototype.entries = function() {
                var items = []
                this.forEach(function(value, name) { items.push([name, value]) })
                return iteratorFor(items)
            }

            if (support.iterable) {
                Headers.prototype[Symbol.iterator] = Headers.prototype.entries
            }

            function consumed(body) {
                if (body.bodyUsed) {
                    return Promise.reject(new TypeError('Already read'))
                }
                body.bodyUsed = true
            }

            function fileReaderReady(reader) {
                return new Promise(function(resolve, reject) {
                    reader.onload = function() {
                        resolve(reader.result)
                    }
                    reader.onerror = function() {
                        reject(reader.error)
                    }
                })
            }

            function readBlobAsArrayBuffer(blob) {
                var reader = new FileReader()
                var promise = fileReaderReady(reader)
                reader.readAsArrayBuffer(blob)
                return promise
            }

            function readBlobAsText(blob) {
                var reader = new FileReader()
                var promise = fileReaderReady(reader)
                reader.readAsText(blob)
                return promise
            }

            function readArrayBufferAsText(buf) {
                var view = new Uint8Array(buf)
                var chars = new Array(view.length)

                for (var i = 0; i < view.length; i++) {
                    chars[i] = String.fromCharCode(view[i])
                }
                return chars.join('')
            }

            function bufferClone(buf) {
                if (buf.slice) {
                    return buf.slice(0)
                } else {
                    var view = new Uint8Array(buf.byteLength)
                    view.set(new Uint8Array(buf))
                    return view.buffer
                }
            }

            function Body() {
                this.bodyUsed = false

                this._initBody = function(body) {
                    this._bodyInit = body
                    if (!body) {
                        this._bodyText = ''
                    } else if (typeof body === 'string') {
                        this._bodyText = body
                    } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
                        this._bodyBlob = body
                    } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
                        this._bodyFormData = body
                    } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
                        this._bodyText = body.toString()
                    } else if (support.arrayBuffer && support.blob && isDataView(body)) {
                        this._bodyArrayBuffer = bufferClone(body.buffer)
                        // IE 10-11 can't handle a DataView body.
                        this._bodyInit = new Blob([this._bodyArrayBuffer])
                    } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
                        this._bodyArrayBuffer = bufferClone(body)
                    } else {
                        throw new Error('unsupported BodyInit type')
                    }

                    if (!this.headers.get('content-type')) {
                        if (typeof body === 'string') {
                            this.headers.set('content-type', 'text/plain;charset=UTF-8')
                        } else if (this._bodyBlob && this._bodyBlob.type) {
                            this.headers.set('content-type', this._bodyBlob.type)
                        } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
                            this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
                        }
                    }
                }

                if (support.blob) {
                    this.blob = function() {
                        var rejected = consumed(this)
                        if (rejected) {
                            return rejected
                        }

                        if (this._bodyBlob) {
                            return Promise.resolve(this._bodyBlob)
                        } else if (this._bodyArrayBuffer) {
                            return Promise.resolve(new Blob([this._bodyArrayBuffer]))
                        } else if (this._bodyFormData) {
                            throw new Error('could not read FormData body as blob')
                        } else {
                            return Promise.resolve(new Blob([this._bodyText]))
                        }
                    }

                    this.arrayBuffer = function() {
                        if (this._bodyArrayBuffer) {
                            return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
                        } else {
                            return this.blob().then(readBlobAsArrayBuffer)
                        }
                    }
                }

                this.text = function() {
                    var rejected = consumed(this)
                    if (rejected) {
                        return rejected
                    }

                    if (this._bodyBlob) {
                        return readBlobAsText(this._bodyBlob)
                    } else if (this._bodyArrayBuffer) {
                        return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
                    } else if (this._bodyFormData) {
                        throw new Error('could not read FormData body as text')
                    } else {
                        return Promise.resolve(this._bodyText)
                    }
                }

                if (support.formData) {
                    this.formData = function() {
                        return this.text().then(decode)
                    }
                }

                this.json = function() {
                    return this.text().then(JSON.parse)
                }

                return this
            }

            // HTTP methods whose capitalization should be normalized
            var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']

            function normalizeMethod(method) {
                var upcased = method.toUpperCase()
                return (methods.indexOf(upcased) > -1) ? upcased : method
            }

            function Request(input, options) {
                options = options || {}
                var body = options.body

                if (input instanceof Request) {
                    if (input.bodyUsed) {
                        throw new TypeError('Already read')
                    }
                    this.url = input.url
                    this.credentials = input.credentials
                    if (!options.headers) {
                        this.headers = new Headers(input.headers)
                    }
                    this.method = input.method
                    this.mode = input.mode
                    if (!body && input._bodyInit != null) {
                        body = input._bodyInit
                        input.bodyUsed = true
                    }
                } else {
                    this.url = String(input)
                }

                this.credentials = options.credentials || this.credentials || 'omit'
                if (options.headers || !this.headers) {
                    this.headers = new Headers(options.headers)
                }
                this.method = normalizeMethod(options.method || this.method || 'GET')
                this.mode = options.mode || this.mode || null
                this.referrer = null

                if ((this.method === 'GET' || this.method === 'HEAD') && body) {
                    throw new TypeError('Body not allowed for GET or HEAD requests')
                }
                this._initBody(body)
            }

            Request.prototype.clone = function() {
                return new Request(this, { body: this._bodyInit })
            }

            function decode(body) {
                var form = new FormData()
                body.trim().split('&').forEach(function(bytes) {
                    if (bytes) {
                        var split = bytes.split('=')
                        var name = split.shift().replace(/\+/g, ' ')
                        var value = split.join('=').replace(/\+/g, ' ')
                        form.append(decodeURIComponent(name), decodeURIComponent(value))
                    }
                })
                return form
            }

            function parseHeaders(rawHeaders) {
                var headers = new Headers()
                rawHeaders.split(/\r?\n/).forEach(function(line) {
                    var parts = line.split(':')
                    var key = parts.shift().trim()
                    if (key) {
                        var value = parts.join(':').trim()
                        headers.append(key, value)
                    }
                })
                return headers
            }

            Body.call(Request.prototype)

            function Response(bodyInit, options) {
                if (!options) {
                    options = {}
                }

                this.type = 'default'
                this.status = 'status' in options ? options.status : 200
                this.ok = this.status >= 200 && this.status < 300
                this.statusText = 'statusText' in options ? options.statusText : 'OK'
                this.headers = new Headers(options.headers)
                this.url = options.url || ''
                this._initBody(bodyInit)
            }

            Body.call(Response.prototype)

            Response.prototype.clone = function() {
                return new Response(this._bodyInit, {
                    status: this.status,
                    statusText: this.statusText,
                    headers: new Headers(this.headers),
                    url: this.url
                })
            }

            Response.error = function() {
                var response = new Response(null, {status: 0, statusText: ''})
                response.type = 'error'
                return response
            }

            var redirectStatuses = [301, 302, 303, 307, 308]

            Response.redirect = function(url, status) {
                if (redirectStatuses.indexOf(status) === -1) {
                    throw new RangeError('Invalid status code')
                }

                return new Response(null, {status: status, headers: {location: url}})
            }

            self.Headers = Headers
            self.Request = Request
            self.Response = Response

            self.fetch = function(input, init) {
                return new Promise(function(resolve, reject) {
                    var request = new Request(input, init)
                    var xhr = new XMLHttpRequest()

                    xhr.onload = function() {
                        var options = {
                            status: xhr.status,
                            statusText: xhr.statusText,
                            headers: parseHeaders(xhr.getAllResponseHeaders() || '')
                        }
                        options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
                        var body = 'response' in xhr ? xhr.response : xhr.responseText
                        resolve(new Response(body, options))
                    }

                    xhr.onerror = function() {
                        reject(new TypeError('Network request failed'))
                    }

                    xhr.ontimeout = function() {
                        reject(new TypeError('Network request failed'))
                    }

                    xhr.open(request.method, request.url, true)

                    if (request.credentials === 'include') {
                        xhr.withCredentials = true
                    }

                    if ('responseType' in xhr && support.blob) {
                        xhr.responseType = 'blob'
                    }

                    request.headers.forEach(function(value, name) {
                        xhr.setRequestHeader(name, value)
                    })

                    xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
                })
            }
            self.fetch.polyfill = true
        })(typeof self !== 'undefined' ? self : this);

    },{}],71:[function(require,module,exports){
        /* jshint node: true */
        'use strict';

        /**
         # wildcard

         Very simple wildcard matching, which is designed to provide the same
         functionality that is found in the
         [eve](https://github.com/adobe-webplatform/eve) eventing library.

         ## Usage

         It works with strings:

         <<< examples/strings.js

         Arrays:

         <<< examples/arrays.js

         Objects (matching against keys):

         <<< examples/objects.js

         While the library works in Node, if you are are looking for file-based
         wildcard matching then you should have a look at:

         <https://github.com/isaacs/node-glob>
         **/

        function WildcardMatcher(text, separator) {
            this.text = text = text || '';
            this.hasWild = ~text.indexOf('*');
            this.separator = separator;
            this.parts = text.split(separator);
        }

        WildcardMatcher.prototype.match = function(input) {
            var matches = true;
            var parts = this.parts;
            var ii;
            var partsCount = parts.length;
            var testParts;

            if (typeof input == 'string' || input instanceof String) {
                if (!this.hasWild && this.text != input) {
                    matches = false;
                } else {
                    testParts = (input || '').split(this.separator);
                    for (ii = 0; matches && ii < partsCount; ii++) {
                        if (parts[ii] === '*')  {
                            continue;
                        } else if (ii < testParts.length) {
                            matches = parts[ii] === testParts[ii];
                        } else {
                            matches = false;
                        }
                    }

                    // If matches, then return the component parts
                    matches = matches && testParts;
                }
            }
            else if (typeof input.splice == 'function') {
                matches = [];

                for (ii = input.length; ii--; ) {
                    if (this.match(input[ii])) {
                        matches[matches.length] = input[ii];
                    }
                }
            }
            else if (typeof input == 'object') {
                matches = {};

                for (var key in input) {
                    if (this.match(key)) {
                        matches[key] = input[key];
                    }
                }
            }

            return matches;
        };

        module.exports = function(text, test, separator) {
            var matcher = new WildcardMatcher(text, separator || /[\/\.]/);
            if (typeof test != 'undefined') {
                return matcher.match(test);
            }

            return matcher;
        };

    },{}],72:[function(require,module,exports){
        'use strict';

        var alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('')
            , length = 64
            , map = {}
            , seed = 0
            , i = 0
            , prev;

        /**
         * Return a string representing the specified number.
         *
         * @param {Number} num The number to convert.
         * @returns {String} The string representation of the number.
         * @api public
         */
        function encode(num) {
            var encoded = '';

            do {
                encoded = alphabet[num % length] + encoded;
                num = Math.floor(num / length);
            } while (num > 0);

            return encoded;
        }

        /**
         * Return the integer value specified by the given string.
         *
         * @param {String} str The string to convert.
         * @returns {Number} The integer value represented by the string.
         * @api public
         */
        function decode(str) {
            var decoded = 0;

            for (i = 0; i < str.length; i++) {
                decoded = decoded * length + map[str.charAt(i)];
            }

            return decoded;
        }

        /**
         * Yeast: A tiny growing id generator.
         *
         * @returns {String} A unique id.
         * @api public
         */
        function yeast() {
            var now = encode(+new Date());

            if (now !== prev) return seed = 0, prev = now;
            return now +'.'+ encode(seed++);
        }

//
// Map each character to its index.
//
        for (; i < length; i++) map[alphabet[i]] = i;

//
// Expose the `yeast`, `encode` and `decode` functions.
//
        yeast.encode = encode;
        yeast.decode = decode;
        module.exports = yeast;

    },{}],73:[function(require,module,exports){
        (function (global){
            'use strict';

            var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

            var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

            var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

            function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

            var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

            var Utils = require('../core/Utils');
            var Translator = require('../core/Translator');
            var ee = require('namespace-emitter');
            var cuid = require('cuid');
            var throttle = require('lodash.throttle');
            var prettyBytes = require('prettier-bytes');
            var match = require('mime-match');
            var DefaultStore = require('../store/DefaultStore');

            /**
             * Uppy Core module.
             * Manages plugins, state updates, acts as an event bus,
             * adds/removes files and metadata.
             *
             * @param {object} opts â€” Uppy options
             */

            var Uppy = function () {
                function Uppy(opts) {
                    var _this = this;

                    _classCallCheck(this, Uppy);

                    var defaultLocale = {
                        strings: {
                            youCanOnlyUploadX: {
                                0: 'You can only upload %{smart_count} file',
                                1: 'You can only upload %{smart_count} files'
                            },
                            youHaveToAtLeastSelectX: {
                                0: 'You have to select at least %{smart_count} file',
                                1: 'You have to select at least %{smart_count} files'
                            },
                            exceedsSize: 'This file exceeds maximum allowed size of',
                            youCanOnlyUploadFileTypes: 'You can only upload:',
                            uppyServerError: 'Connection with Uppy Server failed'
                        }

                        // set default options
                    };var defaultOptions = {
                        id: 'uppy',
                        autoProceed: true,
                        debug: false,
                        restrictions: {
                            maxFileSize: false,
                            maxNumberOfFiles: false,
                            minNumberOfFiles: false,
                            allowedFileTypes: false
                        },
                        meta: {},
                        onBeforeFileAdded: function onBeforeFileAdded(currentFile, files) {
                            return _Promise.resolve();
                        },
                        onBeforeUpload: function onBeforeUpload(files) {
                            return _Promise.resolve();
                        },
                        locale: defaultLocale,
                        store: new DefaultStore()

                        // Merge default options with the ones set by user
                    };this.opts = _extends({}, defaultOptions, opts);

                    this.locale = _extends({}, defaultLocale, this.opts.locale);
                    this.locale.strings = _extends({}, defaultLocale.strings, this.opts.locale.strings);

                    // i18n
                    this.translator = new Translator({ locale: this.locale });
                    this.i18n = this.translator.translate.bind(this.translator);

                    // Container for different types of plugins
                    this.plugins = {};

                    this.translator = new Translator({ locale: this.opts.locale });
                    this.i18n = this.translator.translate.bind(this.translator);
                    this.getState = this.getState.bind(this);
                    this.getPlugin = this.getPlugin.bind(this);
                    this.setFileMeta = this.setFileMeta.bind(this);
                    this.setFileState = this.setFileState.bind(this);
                    this.log = this.log.bind(this);
                    this.info = this.info.bind(this);
                    this.hideInfo = this.hideInfo.bind(this);
                    this.addFile = this.addFile.bind(this);
                    this.removeFile = this.removeFile.bind(this);
                    this.pauseResume = this.pauseResume.bind(this);
                    this._calculateProgress = this._calculateProgress.bind(this);
                    this.updateOnlineStatus = this.updateOnlineStatus.bind(this);
                    this.resetProgress = this.resetProgress.bind(this);

                    this.pauseAll = this.pauseAll.bind(this);
                    this.resumeAll = this.resumeAll.bind(this);
                    this.retryAll = this.retryAll.bind(this);
                    this.cancelAll = this.cancelAll.bind(this);
                    this.retryUpload = this.retryUpload.bind(this);
                    this.upload = this.upload.bind(this);

                    this.emitter = ee();
                    this.on = this.on.bind(this);
                    this.off = this.off.bind(this);
                    this.once = this.emitter.once.bind(this.emitter);
                    this.emit = this.emitter.emit.bind(this.emitter);

                    this.preProcessors = [];
                    this.uploaders = [];
                    this.postProcessors = [];

                    this.store = this.opts.store;
                    this.setState({
                        plugins: {},
                        files: {},
                        currentUploads: {},
                        capabilities: {
                            resumableUploads: false
                        },
                        totalProgress: 0,
                        meta: _extends({}, this.opts.meta),
                        info: {
                            isHidden: true,
                            type: 'info',
                            message: ''
                        }
                    });

                    this._storeUnsubscribe = this.store.subscribe(function (prevState, nextState, patch) {
                        _this.emit('state-update', prevState, nextState, patch);
                        _this.updateAll(nextState);
                    });

                    // for debugging and testing
                    // this.updateNum = 0
                    if (this.opts.debug) {
                        global.uppyLog = '';
                        global[this.opts.id] = this;
                    }
                }

                Uppy.prototype.on = function on(event, callback) {
                    this.emitter.on(event, callback);
                    return this;
                };

                Uppy.prototype.off = function off(event, callback) {
                    this.emitter.off(event, callback);
                    return this;
                };

                /**
                 * Iterate on all plugins and run `update` on them.
                 * Called each time state changes.
                 *
                 */


                Uppy.prototype.updateAll = function updateAll(state) {
                    this.iteratePlugins(function (plugin) {
                        plugin.update(state);
                    });
                };

                /**
                 * Updates state
                 *
                 * @param {patch} object
                 */


                Uppy.prototype.setState = function setState(patch) {
                    this.store.setState(patch);
                };

                /**
                 * Returns current state.
                 */


                Uppy.prototype.getState = function getState() {
                    return this.store.getState();
                };

                /**
                 * Back compat for when this.state is used instead of this.getState().
                 */


                /**
                 * Shorthand to set state for a specific file.
                 */
                Uppy.prototype.setFileState = function setFileState(fileID, state) {
                    var _extends2;

                    this.setState({
                        files: _extends({}, this.getState().files, (_extends2 = {}, _extends2[fileID] = _extends({}, this.getState().files[fileID], state), _extends2))
                    });
                };

                Uppy.prototype.resetProgress = function resetProgress() {
                    var defaultProgress = {
                        percentage: 0,
                        bytesUploaded: 0,
                        uploadComplete: false,
                        uploadStarted: false
                    };
                    var files = _extends({}, this.getState().files);
                    var updatedFiles = {};
                    Object.keys(files).forEach(function (fileID) {
                        var updatedFile = _extends({}, files[fileID]);
                        updatedFile.progress = _extends({}, updatedFile.progress, defaultProgress);
                        updatedFiles[fileID] = updatedFile;
                    });

                    this.setState({
                        files: updatedFiles,
                        totalProgress: 0
                    });

                    // TODO Document on the website
                    this.emit('reset-progress');
                };

                Uppy.prototype.addPreProcessor = function addPreProcessor(fn) {
                    this.preProcessors.push(fn);
                };

                Uppy.prototype.removePreProcessor = function removePreProcessor(fn) {
                    var i = this.preProcessors.indexOf(fn);
                    if (i !== -1) {
                        this.preProcessors.splice(i, 1);
                    }
                };

                Uppy.prototype.addPostProcessor = function addPostProcessor(fn) {
                    this.postProcessors.push(fn);
                };

                Uppy.prototype.removePostProcessor = function removePostProcessor(fn) {
                    var i = this.postProcessors.indexOf(fn);
                    if (i !== -1) {
                        this.postProcessors.splice(i, 1);
                    }
                };

                Uppy.prototype.addUploader = function addUploader(fn) {
                    this.uploaders.push(fn);
                };

                Uppy.prototype.removeUploader = function removeUploader(fn) {
                    var i = this.uploaders.indexOf(fn);
                    if (i !== -1) {
                        this.uploaders.splice(i, 1);
                    }
                };

                Uppy.prototype.setMeta = function setMeta(data) {
                    var updatedMeta = _extends({}, this.getState().meta, data);
                    var updatedFiles = _extends({}, this.getState().files);

                    Object.keys(updatedFiles).forEach(function (fileID) {
                        updatedFiles[fileID] = _extends({}, updatedFiles[fileID], {
                            meta: _extends({}, updatedFiles[fileID].meta, data)
                        });
                    });

                    this.log('Adding metadata:');
                    this.log(data);

                    this.setState({
                        meta: updatedMeta,
                        files: updatedFiles
                    });
                };

                Uppy.prototype.setFileMeta = function setFileMeta(fileID, data) {
                    var updatedFiles = _extends({}, this.getState().files);
                    if (!updatedFiles[fileID]) {
                        this.log('Was trying to set metadata for a file thatâ€™s not with us anymore: ', fileID);
                        return;
                    }
                    var newMeta = _extends({}, updatedFiles[fileID].meta, data);
                    updatedFiles[fileID] = _extends({}, updatedFiles[fileID], {
                        meta: newMeta
                    });
                    this.setState({ files: updatedFiles });
                };

                /**
                 * Get a file object.
                 *
                 * @param {string} fileID The ID of the file object to return.
                 */


                Uppy.prototype.getFile = function getFile(fileID) {
                    return this.getState().files[fileID];
                };

                /**
                 * Check if minNumberOfFiles restriction is reached before uploading.
                 *
                 * @return {boolean}
                 * @private
                 */


                Uppy.prototype._checkMinNumberOfFiles = function _checkMinNumberOfFiles() {
                    var minNumberOfFiles = this.opts.restrictions.minNumberOfFiles;

                    if (Object.keys(this.getState().files).length < minNumberOfFiles) {
                        throw new Error('' + this.i18n('youHaveToAtLeastSelectX', { smart_count: minNumberOfFiles }));
                    }
                };

                /**
                 * Check if file passes a set of restrictions set in options: maxFileSize,
                 * maxNumberOfFiles and allowedFileTypes.
                 *
                 * @param {object} file object to check
                 * @private
                 */


                Uppy.prototype._checkRestrictions = function _checkRestrictions(file) {
                    var _opts$restrictions = this.opts.restrictions,
                        maxFileSize = _opts$restrictions.maxFileSize,
                        maxNumberOfFiles = _opts$restrictions.maxNumberOfFiles,
                        allowedFileTypes = _opts$restrictions.allowedFileTypes;


                    if (maxNumberOfFiles) {
                        if (Object.keys(this.getState().files).length + 1 > maxNumberOfFiles) {
                            throw new Error('' + this.i18n('youCanOnlyUploadX', { smart_count: maxNumberOfFiles }));
                        }
                    }

                    if (allowedFileTypes) {
                        var isCorrectFileType = allowedFileTypes.filter(function (type) {
                            if (!file.type) return false;
                            return match(file.type, type);
                        }).length > 0;

                        if (!isCorrectFileType) {
                            var allowedFileTypesString = allowedFileTypes.join(', ');
                            throw new Error(this.i18n('youCanOnlyUploadFileTypes') + ' ' + allowedFileTypesString);
                        }
                    }

                    if (maxFileSize) {
                        if (file.data.size > maxFileSize) {
                            throw new Error(this.i18n('exceedsSize') + ' ' + prettyBytes(maxFileSize));
                        }
                    }
                };

                /**
                 * Add a new file to `state.files`. This will run `onBeforeFileAdded`,
                 * try to guess file type in a clever way, check file against restrictions,
                 * and start an upload if `autoProceed === true`.
                 *
                 * @param {object} file object to add
                 */


                Uppy.prototype.addFile = function addFile(file) {
                    var _this2 = this;

                    return _Promise.resolve()
                    // Wrap this in a Promise `.then()` handler so errors will reject the Promise
                    // instead of throwing.
                        .then(function () {
                            return _this2.opts.onBeforeFileAdded(file, _this2.getState().files);
                        }).then(function () {
                            return Utils.getFileType(file);
                        }).then(function (fileType) {
                            var updatedFiles = _extends({}, _this2.getState().files);
                            var fileName = void 0;
                            if (file.name) {
                                fileName = file.name;
                            } else if (fileType.split('/')[0] === 'image') {
                                fileName = fileType.split('/')[0] + '.' + fileType.split('/')[1];
                            } else {
                                fileName = 'noname';
                            }
                            var fileExtension = Utils.getFileNameAndExtension(fileName).extension;
                            var isRemote = file.isRemote || false;

                            var fileSize = (file.size || file.data.size);
                            var fileID = Utils.generateFileID(file);

                            var newFile = {
                                source: file.source || '',
                                id: fileID,
                                name: fileName,
                                extension: fileExtension || '',
                                meta: _extends({}, _this2.getState().meta, {
                                    name: fileName,
                                    type: fileType
                                }),
                                type: fileType,
                                data: file.data,
                                progress: {
                                    percentage: 0,
                                    bytesUploaded: 0,
                                    bytesTotal: file.data.size || 0,
                                    uploadComplete: false,
                                    uploadStarted: false
                                },
                                size: fileSize || 0,
                                isRemote: isRemote,
                                remote: file.remote || '',
                                preview: file.preview
                            };

                            _this2._checkRestrictions(newFile);

                            updatedFiles[fileID] = newFile;
                            _this2.setState({ files: updatedFiles });

                            _this2.emit('file-added', newFile);
                            _this2.log('Added file: ' + fileName + ', ' + fileID + ', mime type: ' + fileType);

                            if (_this2.opts.autoProceed && !_this2.scheduledAutoProceed) {
                                _this2.scheduledAutoProceed = setTimeout(function () {
                                    _this2.scheduledAutoProceed = null;
                                    _this2.upload().catch(function (err) {
                                        console.error(err.stack || err.message || err);
                                    });
                                }, 4);
                            }
                        }).catch(function (err) {
                            var message = (typeof err === 'undefined' ? 'undefined' : _typeof(err)) === 'object' ? err.message : err;
                            _this2.log(message);
                            _this2.info(message, 'error', 5000);
                            return _Promise.reject((typeof err === 'undefined' ? 'undefined' : _typeof(err)) === 'object' ? err : new Error(err));
                        });
                };

                Uppy.prototype.removeFile = function removeFile(fileID) {
                    var _this3 = this;

                    var _state = this.state,
                        files = _state.files,
                        currentUploads = _state.currentUploads;

                    var updatedFiles = _extends({}, files);
                    var removedFile = updatedFiles[fileID];
                    delete updatedFiles[fileID];

                    // Remove this file from its `currentUpload`.
                    var updatedUploads = _extends({}, currentUploads);
                    var removeUploads = [];
                    Object.keys(updatedUploads).forEach(function (uploadID) {
                        var newFileIDs = currentUploads[uploadID].fileIDs.filter(function (uploadFileID) {
                            return uploadFileID !== fileID;
                        });
                        // Remove the upload if no files are associated with it anymore.
                        if (newFileIDs.length === 0) {
                            removeUploads.push(uploadID);
                            return;
                        }

                        updatedUploads[uploadID] = _extends({}, currentUploads[uploadID], {
                            fileIDs: newFileIDs
                        });
                    });

                    this.setState({
                        currentUploads: updatedUploads,
                        files: updatedFiles
                    });

                    removeUploads.forEach(function (uploadID) {
                        _this3._removeUpload(uploadID);
                    });

                    this._calculateTotalProgress();
                    this.emit('file-removed', removedFile);

                    // Clean up object URLs.
                    if (removedFile.preview && Utils.isObjectURL(removedFile.preview)) {
                        URL.revokeObjectURL(removedFile.preview);
                    }

                    this.log('Removed file: ' + fileID);
                };

                Uppy.prototype.pauseResume = function pauseResume(fileID) {
                    var updatedFiles = _extends({}, this.getState().files);

                    if (updatedFiles[fileID].uploadComplete) return;

                    var wasPaused = updatedFiles[fileID].isPaused || false;
                    var isPaused = !wasPaused;

                    var updatedFile = _extends({}, updatedFiles[fileID], {
                        isPaused: isPaused
                    });

                    updatedFiles[fileID] = updatedFile;
                    this.setState({ files: updatedFiles });

                    this.emit('upload-pause', fileID, isPaused);

                    return isPaused;
                };

                Uppy.prototype.pauseAll = function pauseAll() {
                    var updatedFiles = _extends({}, this.getState().files);
                    var inProgressUpdatedFiles = Object.keys(updatedFiles).filter(function (file) {
                        return !updatedFiles[file].progress.uploadComplete && updatedFiles[file].progress.uploadStarted;
                    });

                    inProgressUpdatedFiles.forEach(function (file) {
                        var updatedFile = _extends({}, updatedFiles[file], {
                            isPaused: true
                        });
                        updatedFiles[file] = updatedFile;
                    });
                    this.setState({ files: updatedFiles });

                    this.emit('pause-all');
                };

                Uppy.prototype.resumeAll = function resumeAll() {
                    var updatedFiles = _extends({}, this.getState().files);
                    var inProgressUpdatedFiles = Object.keys(updatedFiles).filter(function (file) {
                        return !updatedFiles[file].progress.uploadComplete && updatedFiles[file].progress.uploadStarted;
                    });

                    inProgressUpdatedFiles.forEach(function (file) {
                        var updatedFile = _extends({}, updatedFiles[file], {
                            isPaused: false,
                            error: null
                        });
                        updatedFiles[file] = updatedFile;
                    });
                    this.setState({ files: updatedFiles });

                    this.emit('resume-all');
                };

                Uppy.prototype.retryAll = function retryAll() {
                    var updatedFiles = _extends({}, this.getState().files);
                    var filesToRetry = Object.keys(updatedFiles).filter(function (file) {
                        return updatedFiles[file].error;
                    });

                    filesToRetry.forEach(function (file) {
                        var updatedFile = _extends({}, updatedFiles[file], {
                            isPaused: false,
                            error: null
                        });
                        updatedFiles[file] = updatedFile;
                    });
                    this.setState({
                        files: updatedFiles,
                        error: null
                    });

                    this.emit('retry-all', filesToRetry);

                    var uploadID = this._createUpload(filesToRetry);
                    return this._runUpload(uploadID);
                };

                Uppy.prototype.cancelAll = function cancelAll() {
                    this.emit('cancel-all');
                    this.setState({ files: {}, totalProgress: 0 });
                };

                Uppy.prototype.retryUpload = function retryUpload(fileID) {
                    var updatedFiles = _extends({}, this.getState().files);
                    var updatedFile = _extends({}, updatedFiles[fileID], { error: null, isPaused: false });
                    updatedFiles[fileID] = updatedFile;
                    this.setState({
                        files: updatedFiles
                    });

                    this.emit('upload-retry', fileID);

                    var uploadID = this._createUpload([fileID]);
                    return this._runUpload(uploadID);
                };

                Uppy.prototype.reset = function reset() {
                    this.cancelAll();
                };

                Uppy.prototype._calculateProgress = function _calculateProgress(data) {
                    var fileID = data.id;

                    // skip progress event for a file thatâ€™s been removed
                    if (!this.getFile(fileID)) {
                        this.log('Trying to set progress for a file thatâ€™s been removed: ', fileID);
                        return;
                    }

                    this.setFileState(fileID, {
                        progress: _extends({}, this.getState().files[fileID].progress, {
                            bytesUploaded: data.bytesUploaded,
                            bytesTotal: data.bytesTotal,
                            percentage: Math.floor((data.bytesUploaded / data.bytesTotal * 100).toFixed(2))
                        })
                    });

                    this._calculateTotalProgress();
                };

                Uppy.prototype._calculateTotalProgress = function _calculateTotalProgress() {
                    // calculate total progress, using the number of files currently uploading,
                    // multiplied by 100 and the summ of individual progress of each file
                    var files = _extends({}, this.getState().files);

                    var inProgress = Object.keys(files).filter(function (file) {
                        return files[file].progress.uploadStarted;
                    });
                    var progressMax = inProgress.length * 100;
                    var progressAll = 0;
                    inProgress.forEach(function (file) {
                        progressAll = progressAll + files[file].progress.percentage;
                    });

                    var totalProgress = progressMax === 0 ? 0 : Math.floor((progressAll * 100 / progressMax).toFixed(2));

                    this.setState({
                        totalProgress: totalProgress
                    });
                };

                /**
                 * Registers listeners for all global actions, like:
                 * `error`, `file-removed`, `upload-progress`
                 *
                 */


                Uppy.prototype.actions = function actions() {
                    var _this4 = this;

                    // const log = this.log
                    // this.on('*', function (payload) {
                    //   log(`[Core] Event: ${this.event}`)
                    //   log(payload)
                    // })

                    // stress-test re-rendering
                    // setInterval(() => {
                    //   this.setState({bla: 'bla'})
                    // }, 20)

                    this.on('error', function (error) {
                        _this4.setState({ error: error.message });
                    });

                    this.on('upload-error', function (fileID, error) {
                        _this4.setFileState(fileID, { error: error.message });
                        _this4.setState({ error: error.message });

                        var fileName = _this4.getState().files[fileID].name;
                        var message = 'Failed to upload ' + fileName;
                        if ((typeof error === 'undefined' ? 'undefined' : _typeof(error)) === 'object' && error.message) {
                            message = { message: message, details: error.message };
                        }
                        _this4.info(message, 'error', 5000);
                    });

                    this.on('upload', function () {
                        _this4.setState({ error: null });
                    });

                    // this.on('file-add', (data) => {
                    //   this.addFile(data)
                    // })

                    this.on('file-remove', function (fileID) {
                        _this4.removeFile(fileID);
                    });

                    this.on('upload-started', function (fileID, upload) {
                        var file = _this4.getFile(fileID);
                        _this4.setFileState(fileID, {
                            progress: _extends({}, file.progress, {
                                uploadStarted: Date.now(),
                                uploadComplete: false,
                                percentage: 0,
                                bytesUploaded: 0,
                                bytesTotal: file.size
                            })
                        });
                    });

                    // upload progress events can occur frequently, especially when you have a good
                    // connection to the remote server. Therefore, we are throtteling them to
                    // prevent accessive function calls.
                    // see also: https://github.com/tus/tus-js-client/commit/9940f27b2361fd7e10ba58b09b60d82422183bbb
                    var _throttledCalculateProgress = throttle(this._calculateProgress, 100, { leading: true, trailing: true });

                    this.on('upload-progress', _throttledCalculateProgress);

                    this.on('upload-success', function (fileID, uploadResp, uploadURL) {
                        _this4.setFileState(fileID, {
                            progress: _extends({}, _this4.getState().files[fileID].progress, {
                                uploadComplete: true,
                                percentage: 100
                            }),
                            uploadURL: uploadURL,
                            isPaused: false
                        });

                        _this4._calculateTotalProgress();
                    });

                    this.on('preprocess-progress', function (fileID, progress) {
                        _this4.setFileState(fileID, {
                            progress: _extends({}, _this4.getState().files[fileID].progress, {
                                preprocess: progress
                            })
                        });
                    });

                    this.on('preprocess-complete', function (fileID) {
                        var files = _extends({}, _this4.getState().files);
                        files[fileID] = _extends({}, files[fileID], {
                            progress: _extends({}, files[fileID].progress)
                        });
                        delete files[fileID].progress.preprocess;

                        _this4.setState({ files: files });
                    });

                    this.on('postprocess-progress', function (fileID, progress) {
                        _this4.setFileState(fileID, {
                            progress: _extends({}, _this4.getState().files[fileID].progress, {
                                postprocess: progress
                            })
                        });
                    });

                    this.on('postprocess-complete', function (fileID) {
                        var files = _extends({}, _this4.getState().files);
                        files[fileID] = _extends({}, files[fileID], {
                            progress: _extends({}, files[fileID].progress)
                        });
                        delete files[fileID].progress.postprocess;
                        // TODO should we set some kind of `fullyComplete` property on the file object
                        // so it's easier to see that the file is uploadâ€¦fully completeâ€¦rather than
                        // what we have to do now (`uploadComplete && !postprocess`)

                        _this4.setState({ files: files });
                    });

                    this.on('restored', function () {
                        // Files may have changed--ensure progress is still accurate.
                        _this4._calculateTotalProgress();
                    });

                    // show informer if offline
                    if (typeof window !== 'undefined') {
                        window.addEventListener('online', function () {
                            return _this4.updateOnlineStatus();
                        });
                        window.addEventListener('offline', function () {
                            return _this4.updateOnlineStatus();
                        });
                        setTimeout(function () {
                            return _this4.updateOnlineStatus();
                        }, 3000);
                    }
                };

                Uppy.prototype.updateOnlineStatus = function updateOnlineStatus() {
                    var online = typeof window.navigator.onLine !== 'undefined' ? window.navigator.onLine : true;
                    if (!online) {
                        this.emit('is-offline');
                        this.info('No internet connection', 'error', 0);
                        this.wasOffline = true;
                    } else {
                        this.emit('is-online');
                        if (this.wasOffline) {
                            this.emit('back-online');
                            this.info('Connected!', 'success', 3000);
                            this.wasOffline = false;
                        }
                    }
                };

                Uppy.prototype.getID = function getID() {
                    return this.opts.id;
                };

                /**
                 * Registers a plugin with Core.
                 *
                 * @param {Class} Plugin object
                 * @param {Object} options object that will be passed to Plugin later
                 * @return {Object} self for chaining
                 */


                Uppy.prototype.use = function use(Plugin, opts) {
                    if (typeof Plugin !== 'function') {
                        var msg = 'Expected a plugin class, but got ' + (Plugin === null ? 'null' : typeof Plugin === 'undefined' ? 'undefined' : _typeof(Plugin)) + '.' + ' Please verify that the plugin was imported and spelled correctly.';
                        throw new TypeError(msg);
                    }

                    // Instantiate
                    var plugin = new Plugin(this, opts);
                    var pluginId = plugin.id;
                    this.plugins[plugin.type] = this.plugins[plugin.type] || [];

                    if (!pluginId) {
                        throw new Error('Your plugin must have an id');
                    }

                    if (!plugin.type) {
                        throw new Error('Your plugin must have a type');
                    }

                    var existsPluginAlready = this.getPlugin(pluginId);
                    if (existsPluginAlready) {
                        var _msg = 'Already found a plugin named \'' + existsPluginAlready.id + '\'.\n        Tried to use: \'' + pluginId + '\'.\n        Uppy is currently limited to running one of every plugin.\n        Share your use case with us over at\n        https://github.com/transloadit/uppy/issues/\n        if you want us to reconsider.';
                        throw new Error(_msg);
                    }

                    this.plugins[plugin.type].push(plugin);
                    plugin.install();

                    return this;
                };

                /**
                 * Find one Plugin by name.
                 *
                 * @param string name description
                 */


                Uppy.prototype.getPlugin = function getPlugin(name) {
                    var foundPlugin = false;
                    this.iteratePlugins(function (plugin) {
                        var pluginName = plugin.id;
                        if (pluginName === name) {
                            foundPlugin = plugin;
                            return false;
                        }
                    });
                    return foundPlugin;
                };

                /**
                 * Iterate through all `use`d plugins.
                 *
                 * @param function method description
                 */


                Uppy.prototype.iteratePlugins = function iteratePlugins(method) {
                    var _this5 = this;

                    Object.keys(this.plugins).forEach(function (pluginType) {
                        _this5.plugins[pluginType].forEach(method);
                    });
                };

                /**
                 * Uninstall and remove a plugin.
                 *
                 * @param {Plugin} instance The plugin instance to remove.
                 */


                Uppy.prototype.removePlugin = function removePlugin(instance) {
                    var list = this.plugins[instance.type];

                    if (instance.uninstall) {
                        instance.uninstall();
                    }

                    var index = list.indexOf(instance);
                    if (index !== -1) {
                        list.splice(index, 1);
                    }
                };

                /**
                 * Uninstall all plugins and close down this Uppy instance.
                 */


                Uppy.prototype.close = function close() {
                    this.reset();

                    this._storeUnsubscribe();

                    this.iteratePlugins(function (plugin) {
                        plugin.uninstall();
                    });
                };

                /**
                 * Set info message in `state.info`, so that UI plugins like `Informer`
                 * can display the message.
                 *
                 * @param {string} msg Message to be displayed by the informer
                 */

                Uppy.prototype.info = function info(message) {
                    var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'info';
                    var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 3000;

                    var isComplexMessage = (typeof message === 'undefined' ? 'undefined' : _typeof(message)) === 'object';

                    this.setState({
                        info: {
                            isHidden: false,
                            type: type,
                            message: isComplexMessage ? message.message : message,
                            details: isComplexMessage ? message.details : null
                        }
                    });

                    this.emit('info-visible');

                    window.clearTimeout(this.infoTimeoutID);
                    if (duration === 0) {
                        this.infoTimeoutID = undefined;
                        return;
                    }

                    // hide the informer after `duration` milliseconds
                    this.infoTimeoutID = setTimeout(this.hideInfo, duration);
                };

                Uppy.prototype.hideInfo = function hideInfo() {
                    var newInfo = _extends({}, this.getState().info, {
                        isHidden: true
                    });
                    this.setState({
                        info: newInfo
                    });
                    this.emit('info-hidden');
                };

                /**
                 * Logs stuff to console, only if `debug` is set to true. Silent in production.
                 *
                 * @param {String|Object} msg to log
                 * @param {String} type optional `error` or `warning`
                 */


                Uppy.prototype.log = function log(msg, type) {
                    if (!this.opts.debug) {
                        return;
                    }

                    var message = '[Uppy] [' + Utils.getTimeStamp() + '] ' + msg;

                    global.uppyLog = global.uppyLog + '\n' + 'DEBUG LOG: ' + msg;

                    if (type === 'error') {
                        console.error(message);
                        return;
                    }

                    if (type === 'warning') {
                        console.warn(message);
                        return;
                    }

                    if (msg === '' + msg) {
                        console.log(message);
                    } else {
                        message = '[Uppy] [' + Utils.getTimeStamp() + ']';
                        console.log(message);
                        console.dir(msg);
                    }
                };

                /**
                 * Initializes actions.
                 *
                 */


                Uppy.prototype.run = function run() {
                    this.log('Core is run, initializing actions...');
                    this.actions();

                    return this;
                };

                /**
                 * Restore an upload by its ID.
                 */


                Uppy.prototype.restore = function restore(uploadID) {
                    this.log('Core: attempting to restore upload "' + uploadID + '"');

                    if (!this.getState().currentUploads[uploadID]) {
                        this._removeUpload(uploadID);
                        return _Promise.reject(new Error('Nonexistent upload'));
                    }

                    return this._runUpload(uploadID);
                };

                /**
                 * Create an upload for a bunch of files.
                 *
                 * @param {Array<string>} fileIDs File IDs to include in this upload.
                 * @return {string} ID of this upload.
                 */


                Uppy.prototype._createUpload = function _createUpload(fileIDs) {
                    var _extends3;

                    var uploadID = cuid();

                    this.emit('upload', {
                        id: uploadID,
                        fileIDs: fileIDs
                    });

                    this.setState({
                        currentUploads: _extends({}, this.getState().currentUploads, (_extends3 = {}, _extends3[uploadID] = {
                            fileIDs: fileIDs,
                            step: 0,
                            result: {}
                        }, _extends3))
                    });

                    return uploadID;
                };

                Uppy.prototype._getUpload = function _getUpload(uploadID) {
                    return this.getState().currentUploads[uploadID];
                };

                /**
                 * Add data to an upload's result object.
                 *
                 * @param {string} uploadID The ID of the upload.
                 * @param {object} data Data properties to add to the result object.
                 */


                Uppy.prototype.addResultData = function addResultData(uploadID, data) {
                    var _extends4;

                    var currentUploads = this.getState().currentUploads;
                    var currentUpload = _extends({}, currentUploads[uploadID], {
                        result: _extends({}, currentUploads[uploadID].result, data)
                    });
                    this.setState({
                        currentUploads: _extends({}, currentUploads, (_extends4 = {}, _extends4[uploadID] = currentUpload, _extends4))
                    });
                };

                /**
                 * Remove an upload, eg. if it has been canceled or completed.
                 *
                 * @param {string} uploadID The ID of the upload.
                 */


                Uppy.prototype._removeUpload = function _removeUpload(uploadID) {
                    var currentUploads = _extends({}, this.getState().currentUploads);
                    delete currentUploads[uploadID];

                    this.setState({
                        currentUploads: currentUploads
                    });
                };

                /**
                 * Run an upload. This picks up where it left off in case the upload is being restored.
                 *
                 * @private
                 */


                Uppy.prototype._runUpload = function _runUpload(uploadID) {
                    var _this6 = this;

                    var uploadData = this.getState().currentUploads[uploadID];
                    var fileIDs = uploadData.fileIDs;
                    var restoreStep = uploadData.step;

                    var steps = [].concat(this.preProcessors, this.uploaders, this.postProcessors);
                    var lastStep = _Promise.resolve();
                    steps.forEach(function (fn, step) {
                        // Skip this step if we are restoring and have already completed this step before.
                        if (step < restoreStep) {
                            return;
                        }

                        lastStep = lastStep.then(function () {
                            var _extends5;

                            var _getState = _this6.getState(),
                                currentUploads = _getState.currentUploads;

                            var currentUpload = _extends({}, currentUploads[uploadID], {
                                step: step
                            });
                            _this6.setState({
                                currentUploads: _extends({}, currentUploads, (_extends5 = {}, _extends5[uploadID] = currentUpload, _extends5))
                            });
                            // TODO give this the `currentUpload` object as its only parameter maybe?
                            // Otherwise when more metadata may be added to the upload this would keep getting more parameters
                            return fn(fileIDs, uploadID);
                        }).then(function (result) {
                            return null;
                        });
                    });

                    // Not returning the `catch`ed promise, because we still want to return a rejected
                    // promise from this method if the upload failed.
                    lastStep.catch(function (err) {
                        _this6.emit('error', err);

                        _this6._removeUpload(uploadID);
                    });

                    return lastStep.then(function () {
                        var files = fileIDs.map(function (fileID) {
                            return _this6.getFile(fileID);
                        });
                        var successful = files.filter(function (file) {
                            return file && !file.error;
                        });
                        var failed = files.filter(function (file) {
                            return file && file.error;
                        });
                        _this6.addResultData(uploadID, { successful: successful, failed: failed, uploadID: uploadID });

                        var _getState2 = _this6.getState(),
                            currentUploads = _getState2.currentUploads;

                        var result = currentUploads[uploadID].result;
                        _this6.emit('complete', result);
                        // Compatibility with pre-0.21
                        _this6.emit('success', fileIDs);

                        _this6._removeUpload(uploadID);

                        return result;
                    });
                };

                /**
                 * Start an upload for all the files that are not currently being uploaded.
                 *
                 * @return {Promise}
                 */


                Uppy.prototype.upload = function upload() {
                    var _this7 = this;

                    if (!this.plugins.uploader) {
                        this.log('No uploader type plugins are used', 'warning');
                    }

                    return _Promise.resolve().then(function () {
                        return _this7.opts.onBeforeUpload(_this7.getState().files);
                    }).then(function () {
                        return _this7._checkMinNumberOfFiles();
                    }).then(function () {
                        var _getState3 = _this7.getState(),
                            currentUploads = _getState3.currentUploads;
                        // get a list of files that are currently assigned to uploads


                        var currentlyUploadingFiles = Object.keys(currentUploads).reduce(function (prev, curr) {
                            return prev.concat(currentUploads[curr].fileIDs);
                        }, []);

                        var waitingFileIDs = [];
                        Object.keys(_this7.getState().files).forEach(function (fileID) {
                            var file = _this7.getFile(fileID);
                            // if the file hasn't started uploading and hasn't already been assigned to an upload..
                            if (!file.progress.uploadStarted && currentlyUploadingFiles.indexOf(fileID) === -1) {
                                waitingFileIDs.push(file.id);
                            }
                        });

                        var uploadID = _this7._createUpload(waitingFileIDs);
                        return _this7._runUpload(uploadID);
                    }).catch(function (err) {
                        var message = (typeof err === 'undefined' ? 'undefined' : _typeof(err)) === 'object' ? err.message : err;
                        _this7.log(message);
                        _this7.info(message, 'error', 4000);
                        return _Promise.reject((typeof err === 'undefined' ? 'undefined' : _typeof(err)) === 'object' ? err : new Error(err));
                    });
                };

                _createClass(Uppy, [{
                    key: 'state',
                    get: function get() {
                        return this.getState();
                    }
                }]);

                return Uppy;
            }();

            module.exports = function (opts) {
                return new Uppy(opts);
            };
// Expose class constructor.
            module.exports.Uppy = Uppy;

        }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})

    },{"../core/Translator":75,"../core/Utils":77,"../store/DefaultStore":134,"cuid":11,"es6-promise":33,"lodash.throttle":40,"mime-match":41,"namespace-emitter":43,"prettier-bytes":47}],74:[function(require,module,exports){
        'use strict';

        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var preact = require('preact');

        var _require = require('../core/Utils'),
            findDOMElement = _require.findDOMElement;

        /**
         * Boilerplate that all Plugins share - and should not be used
         * directly. It also shows which methods final plugins should implement/override,
         * this deciding on structure.
         *
         * @param {object} main Uppy core object
         * @param {object} object with plugin options
         * @return {array | string} files or success/fail message
         */


        module.exports = function () {
            function Plugin(uppy, opts) {
                _classCallCheck(this, Plugin);

                this.uppy = uppy;
                this.opts = opts || {};

                this.update = this.update.bind(this);
                this.mount = this.mount.bind(this);
                this.install = this.install.bind(this);
                this.uninstall = this.uninstall.bind(this);
            }

            Plugin.prototype.getPluginState = function getPluginState() {
                return this.uppy.state.plugins[this.id];
            };

            Plugin.prototype.setPluginState = function setPluginState(update) {
                var plugins = _extends({}, this.uppy.state.plugins);
                plugins[this.id] = _extends({}, plugins[this.id], update);

                this.uppy.setState({
                    plugins: plugins
                });
            };

            Plugin.prototype.update = function update(state) {
                if (typeof this.el === 'undefined') {
                    return;
                }

                if (this.updateUI) {
                    this.updateUI(state);
                }
            };

            /**
             * Check if supplied `target` is a DOM element or an `object`.
             * If itâ€™s an object â€” target is a plugin, and we search `plugins`
             * for a plugin with same name and return its target.
             *
             * @param {String|Object} target
             *
             */


            Plugin.prototype.mount = function mount(target, plugin) {
                var _this = this;

                var callerPluginName = plugin.id;

                var targetElement = findDOMElement(target);

                if (targetElement) {
                    this.updateUI = function (state) {
                        _this.el = preact.render(_this.render(state), targetElement, _this.el);
                    };

                    this.uppy.log('Installing ' + callerPluginName + ' to a DOM element');

                    // clear everything inside the target container
                    if (this.opts.replaceTargetContent) {
                        targetElement.innerHTML = '';
                    }

                    this.el = preact.render(this.render(this.uppy.state), targetElement);

                    return this.el;
                }

                var targetPlugin = void 0;
                if ((typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target instanceof Plugin) {
                    // Targeting a plugin *instance*
                    targetPlugin = target;
                } else if (typeof target === 'function') {
                    // Targeting a plugin type
                    var Target = target;
                    // Find the target plugin instance.
                    this.uppy.iteratePlugins(function (plugin) {
                        if (plugin instanceof Target) {
                            targetPlugin = plugin;
                            return false;
                        }
                    });
                }

                if (targetPlugin) {
                    var targetPluginName = targetPlugin.id;
                    this.uppy.log('Installing ' + callerPluginName + ' to ' + targetPluginName);
                    this.el = targetPlugin.addTarget(plugin);
                    return this.el;
                }

                this.uppy.log('Not installing ' + callerPluginName);
                throw new Error('Invalid target option given to ' + callerPluginName);
            };

            Plugin.prototype.render = function render(state) {
                throw new Error('Extend the render method to add your plugin to a DOM element');
            };

            Plugin.prototype.addTarget = function addTarget(plugin) {
                throw new Error('Extend the addTarget method to add your plugin to another plugin\'s target');
            };

            Plugin.prototype.unmount = function unmount() {
                if (this.el && this.el.parentNode) {
                    this.el.parentNode.removeChild(this.el);
                }
                // this.target = null
            };

            Plugin.prototype.install = function install() {};

            Plugin.prototype.uninstall = function uninstall() {
                this.unmount();
            };

            return Plugin;
        }();

    },{"../core/Utils":77,"preact":46}],75:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        /**
         * Translates strings with interpolation & pluralization support.
         * Extensible with custom dictionaries and pluralization functions.
         *
         * Borrows heavily from and inspired by Polyglot https://github.com/airbnb/polyglot.js,
         * basically a stripped-down version of it. Differences: pluralization functions are not hardcoded
         * and can be easily added among with dictionaries, nested objects are used for pluralization
         * as opposed to `||||` delimeter
         *
         * Usage example: `translator.translate('files_chosen', {smart_count: 3})`
         *
         * @param {object} opts
         */
        module.exports = function () {
            function Translator(opts) {
                _classCallCheck(this, Translator);

                var defaultOptions = {
                    locale: {
                        strings: {},
                        pluralize: function pluralize(n) {
                            if (n === 1) {
                                return 0;
                            }
                            return 1;
                        }
                    }
                };

                this.opts = _extends({}, defaultOptions, opts);
                this.locale = _extends({}, defaultOptions.locale, opts.locale);

                // console.log(this.opts.locale)

                // this.locale.pluralize = this.locale ? this.locale.pluralize : defaultPluralize
                // this.locale.strings = Object.assign({}, en_US.strings, this.opts.locale.strings)
            }

            /**
             * Takes a string with placeholder variables like `%{smart_count} file selected`
             * and replaces it with values from options `{smart_count: 5}`
             *
             * @license https://github.com/airbnb/polyglot.js/blob/master/LICENSE
             * taken from https://github.com/airbnb/polyglot.js/blob/master/lib/polyglot.js#L299
             *
             * @param {string} phrase that needs interpolation, with placeholders
             * @param {object} options with values that will be used to replace placeholders
             * @return {string} interpolated
             */


            Translator.prototype.interpolate = function interpolate(phrase, options) {
                var replace = String.prototype.replace;
                var dollarRegex = /\$/g;
                var dollarBillsYall = '$$$$';

                for (var arg in options) {
                    if (arg !== '_' && options.hasOwnProperty(arg)) {
                        // Ensure replacement value is escaped to prevent special $-prefixed
                        // regex replace tokens. the "$$$$" is needed because each "$" needs to
                        // be escaped with "$" itself, and we need two in the resulting output.
                        var replacement = options[arg];
                        if (typeof replacement === 'string') {
                            replacement = replace.call(options[arg], dollarRegex, dollarBillsYall);
                        }
                        // We create a new `RegExp` each time instead of using a more-efficient
                        // string replace so that the same argument can be replaced multiple times
                        // in the same phrase.
                        phrase = replace.call(phrase, new RegExp('%\\{' + arg + '\\}', 'g'), replacement);
                    }
                }
                return phrase;
            };

            /**
             * Public translate method
             *
             * @param {string} key
             * @param {object} options with values that will be used later to replace placeholders in string
             * @return {string} translated (and interpolated)
             */


            Translator.prototype.translate = function translate(key, options) {
                if (options && options.smart_count) {
                    var plural = this.locale.pluralize(options.smart_count);
                    return this.interpolate(this.opts.locale.strings[key][plural], options);
                }

                return this.interpolate(this.opts.locale.strings[key], options);
            };

            return Translator;
        }();

    },{}],76:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var ee = require('namespace-emitter');

        module.exports = function () {
            function UppySocket(opts) {
                var _this = this;

                _classCallCheck(this, UppySocket);

                this.queued = [];
                this.isOpen = false;
                this.socket = new WebSocket(opts.target);
                this.emitter = ee();

                this.socket.onopen = function (e) {
                    _this.isOpen = true;

                    while (_this.queued.length > 0 && _this.isOpen) {
                        var first = _this.queued[0];
                        _this.send(first.action, first.payload);
                        _this.queued = _this.queued.slice(1);
                    }
                };

                this.socket.onclose = function (e) {
                    _this.isOpen = false;
                };

                this._handleMessage = this._handleMessage.bind(this);

                this.socket.onmessage = this._handleMessage;

                this.close = this.close.bind(this);
                this.emit = this.emit.bind(this);
                this.on = this.on.bind(this);
                this.once = this.once.bind(this);
                this.send = this.send.bind(this);
            }

            UppySocket.prototype.close = function close() {
                return this.socket.close();
            };

            UppySocket.prototype.send = function send(action, payload) {
                // attach uuid

                if (!this.isOpen) {
                    this.queued.push({ action: action, payload: payload });
                    return;
                }

                this.socket.send(JSON.stringify({
                    action: action,
                    payload: payload
                }));
            };

            UppySocket.prototype.on = function on(action, handler) {
                console.log(action);
                this.emitter.on(action, handler);
            };

            UppySocket.prototype.emit = function emit(action, payload) {
                console.log(action);
                this.emitter.emit(action, payload);
            };

            UppySocket.prototype.once = function once(action, handler) {
                this.emitter.once(action, handler);
            };

            UppySocket.prototype._handleMessage = function _handleMessage(e) {
                try {
                    var message = JSON.parse(e.data);
                    console.log(message);
                    this.emit(message.action, message.payload);
                } catch (err) {
                    console.log(err);
                }
            };

            return UppySocket;
        }();

    },{"namespace-emitter":43}],77:[function(require,module,exports){
        'use strict';

        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var throttle = require('lodash.throttle');
// we inline file-type module, as opposed to using the NPM version,
// because of this https://github.com/sindresorhus/file-type/issues/78
// and https://github.com/sindresorhus/copy-text-to-clipboard/issues/5
        var fileType = require('../vendor/file-type');

        /**
         * A collection of small utility functions that help with dom manipulation, adding listeners,
         * promises and other good things.
         *
         * @module Utils
         */

        function isTouchDevice() {
            return 'ontouchstart' in window || // works on most browsers
                navigator.maxTouchPoints; // works on IE10/11 and Surface
        }

        function truncateString(str, length) {
            if (str.length > length) {
                return str.substr(0, length / 2) + '...' + str.substr(str.length - length / 4, str.length);
            }
            return str;

            // more precise version if needed
            // http://stackoverflow.com/a/831583
        }

        function secondsToTime(rawSeconds) {
            var hours = Math.floor(rawSeconds / 3600) % 24;
            var minutes = Math.floor(rawSeconds / 60) % 60;
            var seconds = Math.floor(rawSeconds % 60);

            return { hours: hours, minutes: minutes, seconds: seconds };
        }

        /**
         * Converts list into array
         */
        function toArray(list) {
            return Array.prototype.slice.call(list || [], 0);
        }

        /**
         * Returns a timestamp in the format of `hours:minutes:seconds`
         */
        function getTimeStamp() {
            var date = new Date();
            var hours = pad(date.getHours().toString());
            var minutes = pad(date.getMinutes().toString());
            var seconds = pad(date.getSeconds().toString());
            return hours + ':' + minutes + ':' + seconds;
        }

        /**
         * Adds zero to strings shorter than two characters
         */
        function pad(str) {
            return str.length !== 2 ? 0 + str : str;
        }

        /**
         * Takes a file object and turns it into fileID, by converting file.name to lowercase,
         * removing extra characters and adding type, size and lastModified
         *
         * @param {Object} file
         * @return {String} the fileID
         *
         */
        function generateFileID(file) {
            // filter is needed to not join empty values with `-`
            return ['uppy', file.name ? file.name.toLowerCase().replace(/[^A-Z0-9]/ig, '') : '', file.type, file.data.size, file.data.lastModified].filter(function (val) {
                return val;
            }).join('-');
        }

        /**
         * Runs an array of promise-returning functions in sequence.
         */
        function runPromiseSequence(functions) {
            for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
                args[_key - 1] = arguments[_key];
            }

            var promise = _Promise.resolve();
            functions.forEach(function (func) {
                promise = promise.then(function () {
                    return func.apply(undefined, args);
                });
            });
            return promise;
        }

        function isPreviewSupported(fileType) {
            if (!fileType) return false;
            var fileTypeSpecific = fileType.split('/')[1];
            // list of images that browsers can preview
            if (/^(jpeg|gif|png|svg|svg\+xml|bmp)$/.test(fileTypeSpecific)) {
                return true;
            }
            return false;
        }

        function getArrayBuffer(chunk) {
            return new _Promise(function (resolve, reject) {
                var reader = new FileReader();
                reader.addEventListener('load', function (e) {
                    // e.target.result is an ArrayBuffer
                    resolve(e.target.result);
                });
                reader.addEventListener('error', function (err) {
                    console.error('FileReader error' + err);
                    reject(err);
                });
                // file-type only needs the first 4100 bytes
                reader.readAsArrayBuffer(chunk);
            });
        }

        function getFileType(file) {
            var extensionsToMime = {
                'md': 'text/markdown',
                'markdown': 'text/markdown',
                'mp4': 'video/mp4',
                'mp3': 'audio/mp3',
                'svg': 'image/svg+xml',
                'jpg': 'image/jpeg',
                'png': 'image/png',
                'gif': 'image/gif'
            };

            var fileExtension = file.name ? getFileNameAndExtension(file.name).extension : null;

            if (file.isRemote) {
                // some remote providers do not support file types
                var mime = file.type ? file.type : extensionsToMime[fileExtension];
                return _Promise.resolve(mime);
            }

            // 1. try to determine file type from magic bytes with file-type module
            // this should be the most trustworthy way
            var chunk = file.data.slice(0, 4100);
            return getArrayBuffer(chunk).then(function (buffer) {
                var type = fileType(buffer);
                if (type && type.mime) {
                    return type.mime;
                }

                // 2. if thatâ€™s no good, check if mime type is set in the file object
                if (file.type) {
                    return file.type;
                }

                // 3. if thatâ€™s no good, see if we can map extension to a mime type
                if (fileExtension && extensionsToMime[fileExtension]) {
                    return extensionsToMime[fileExtension];
                }

                // if all fails, well, return empty
                return null;
            }).catch(function () {
                return null;
            });
        }

// TODO Check which types are actually supported in browsers. Chrome likes webm
// from my testing, but we may need more.
// We could use a library but they tend to contain dozens of KBs of mappings,
// most of which will go unused, so not sure if that's worth it.
        var mimeToExtensions = {
            'video/ogg': 'ogv',
            'audio/ogg': 'ogg',
            'video/webm': 'webm',
            'audio/webm': 'webm',
            'video/mp4': 'mp4',
            'audio/mp3': 'mp3'
        };

        function getFileTypeExtension(mimeType) {
            return mimeToExtensions[mimeType] || null;
        }

        /**
         * Takes a full filename string and returns an object {name, extension}
         *
         * @param {string} fullFileName
         * @return {object} {name, extension}
         */
        function getFileNameAndExtension(fullFileName) {
            var re = /(?:\.([^.]+))?$/;
            var fileExt = re.exec(fullFileName)[1];
            var fileName = fullFileName.replace('.' + fileExt, '');
            return {
                name: fileName,
                extension: fileExt
            };
        }

        /**
         * Check if a URL string is an object URL from `URL.createObjectURL`.
         *
         * @param {string} url
         * @return {boolean}
         */
        function isObjectURL(url) {
            return url.indexOf('blob:') === 0;
        }

        function getProportionalHeight(img, width) {
            var aspect = img.width / img.height;
            return Math.round(width / aspect);
        }

        /**
         * Create a thumbnail for the given Uppy file object.
         *
         * @param {{data: Blob}} file
         * @param {number} width
         * @return {Promise}
         */
        function createThumbnail(file, targetWidth) {
            var originalUrl = URL.createObjectURL(file.data);
            var onload = new _Promise(function (resolve, reject) {
                var image = new Image();
                image.src = originalUrl;
                image.onload = function () {
                    URL.revokeObjectURL(originalUrl);
                    resolve(image);
                };
                image.onerror = function () {
                    // The onerror event is totally useless unfortunately, as far as I know
                    URL.revokeObjectURL(originalUrl);
                    reject(new Error('Could not create thumbnail'));
                };
            });

            return onload.then(function (image) {
                var targetHeight = getProportionalHeight(image, targetWidth);
                var canvas = resizeImage(image, targetWidth, targetHeight);
                return canvasToBlob(canvas, 'image/png');
            }).then(function (blob) {
                return URL.createObjectURL(blob);
            });
        }

        /**
         * Resize an image to the target `width` and `height`.
         *
         * Returns a Canvas with the resized image on it.
         */
        function resizeImage(image, targetWidth, targetHeight) {
            var sourceWidth = image.width;
            var sourceHeight = image.height;

            if (targetHeight < image.height / 2) {
                var steps = Math.floor(Math.log(image.width / targetWidth) / Math.log(2));
                var stepScaled = downScaleInSteps(image, steps);
                image = stepScaled.image;
                sourceWidth = stepScaled.sourceWidth;
                sourceHeight = stepScaled.sourceHeight;
            }

            var canvas = document.createElement('canvas');
            canvas.width = targetWidth;
            canvas.height = targetHeight;

            var context = canvas.getContext('2d');
            context.drawImage(image, 0, 0, sourceWidth, sourceHeight, 0, 0, targetWidth, targetHeight);

            return canvas;
        }

        /**
         * Downscale an image by 50% `steps` times.
         */
        function downScaleInSteps(image, steps) {
            var source = image;
            var currentWidth = source.width;
            var currentHeight = source.height;

            for (var i = 0; i < steps; i += 1) {
                var canvas = document.createElement('canvas');
                var context = canvas.getContext('2d');
                canvas.width = currentWidth / 2;
                canvas.height = currentHeight / 2;
                context.drawImage(source,
                    // The entire source image. We pass width and height here,
                    // because we reuse this canvas, and should only scale down
                    // the part of the canvas that contains the previous scale step.
                    0, 0, currentWidth, currentHeight,
                    // Draw to 50% size
                    0, 0, currentWidth / 2, currentHeight / 2);
                currentWidth /= 2;
                currentHeight /= 2;
                source = canvas;
            }

            return {
                image: source,
                sourceWidth: currentWidth,
                sourceHeight: currentHeight
            };
        }

        /**
         * Save a <canvas> element's content to a Blob object.
         *
         * @param {HTMLCanvasElement} canvas
         * @return {Promise}
         */
        function canvasToBlob(canvas, type, quality) {
            if (canvas.toBlob) {
                return new _Promise(function (resolve) {
                    canvas.toBlob(resolve, type, quality);
                });
            }
            return _Promise.resolve().then(function () {
                return dataURItoBlob(canvas.toDataURL(type, quality), {});
            });
        }

        function dataURItoBlob(dataURI, opts, toFile) {
            // get the base64 data
            var data = dataURI.split(',')[1];

            // user may provide mime type, if not get it from data URI
            var mimeType = opts.mimeType || dataURI.split(',')[0].split(':')[1].split(';')[0];

            // default to plain/text if data URI has no mimeType
            if (mimeType == null) {
                mimeType = 'plain/text';
            }

            var binary = atob(data);
            var array = [];
            for (var i = 0; i < binary.length; i++) {
                array.push(binary.charCodeAt(i));
            }

            // Convert to a File?
            if (toFile) {
                return new File([new Uint8Array(array)], opts.name || '', { type: mimeType });
            }

            return new Blob([new Uint8Array(array)], { type: mimeType });
        }

        function dataURItoFile(dataURI, opts) {
            return dataURItoBlob(dataURI, opts, true);
        }

        /**
         * Copies text to clipboard by creating an almost invisible textarea,
         * adding text there, then running execCommand('copy').
         * Falls back to prompt() when the easy way fails (hello, Safari!)
         * From http://stackoverflow.com/a/30810322
         *
         * @param {String} textToCopy
         * @param {String} fallbackString
         * @return {Promise}
         */
        function copyToClipboard(textToCopy, fallbackString) {
            fallbackString = fallbackString || 'Copy the URL below';

            return new _Promise(function (resolve) {
                var textArea = document.createElement('textarea');
                textArea.setAttribute('style', {
                    position: 'fixed',
                    top: 0,
                    left: 0,
                    width: '2em',
                    height: '2em',
                    padding: 0,
                    border: 'none',
                    outline: 'none',
                    boxShadow: 'none',
                    background: 'transparent'
                });

                textArea.value = textToCopy;
                document.body.appendChild(textArea);
                textArea.select();

                var magicCopyFailed = function magicCopyFailed() {
                    document.body.removeChild(textArea);
                    window.prompt(fallbackString, textToCopy);
                    resolve();
                };

                try {
                    var successful = document.execCommand('copy');
                    if (!successful) {
                        return magicCopyFailed('copy command unavailable');
                    }
                    document.body.removeChild(textArea);
                    return resolve();
                } catch (err) {
                    document.body.removeChild(textArea);
                    return magicCopyFailed(err);
                }
            });
        }

        function getSpeed(fileProgress) {
            if (!fileProgress.bytesUploaded) return 0;

            var timeElapsed = new Date() - fileProgress.uploadStarted;
            var uploadSpeed = fileProgress.bytesUploaded / (timeElapsed / 1000);
            return uploadSpeed;
        }

        function getBytesRemaining(fileProgress) {
            return fileProgress.bytesTotal - fileProgress.bytesUploaded;
        }

        function getETA(fileProgress) {
            if (!fileProgress.bytesUploaded) return 0;

            var uploadSpeed = getSpeed(fileProgress);
            var bytesRemaining = getBytesRemaining(fileProgress);
            var secondsRemaining = Math.round(bytesRemaining / uploadSpeed * 10) / 10;

            return secondsRemaining;
        }

        function prettyETA(seconds) {
            var time = secondsToTime(seconds);

            // Only display hours and minutes if they are greater than 0 but always
            // display minutes if hours is being displayed
            // Display a leading zero if the there is a preceding unit: 1m 05s, but 5s
            var hoursStr = time.hours ? time.hours + 'h ' : '';
            var minutesVal = time.hours ? ('0' + time.minutes).substr(-2) : time.minutes;
            var minutesStr = minutesVal ? minutesVal + 'm ' : '';
            var secondsVal = minutesVal ? ('0' + time.seconds).substr(-2) : time.seconds;
            var secondsStr = secondsVal + 's';

            return '' + hoursStr + minutesStr + secondsStr;
        }

        /**
         * Check if an object is a DOM element. Duck-typing based on `nodeType`.
         *
         * @param {*} obj
         */
        function isDOMElement(obj) {
            return obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && obj.nodeType === Node.ELEMENT_NODE;
        }

        /**
         * Find a DOM element.
         *
         * @param {Node|string} element
         * @return {Node|null}
         */
        function findDOMElement(element) {
            if (typeof element === 'string') {
                return document.querySelector(element);
            }

            if ((typeof element === 'undefined' ? 'undefined' : _typeof(element)) === 'object' && isDOMElement(element)) {
                return element;
            }
        }

        /**
         * Find one or more DOM elements.
         *
         * @param {string} element
         * @return {Array|null}
         */
        function findAllDOMElements(element) {
            if (typeof element === 'string') {
                var elements = [].slice.call(document.querySelectorAll(element));
                return elements.length > 0 ? elements : null;
            }

            if ((typeof element === 'undefined' ? 'undefined' : _typeof(element)) === 'object' && isDOMElement(element)) {
                return [element];
            }
        }

        function getSocketHost(url) {
            // get the host domain
            var regex = /^(?:https?:\/\/|\/\/)?(?:[^@\n]+@)?(?:www\.)?([^\n]+)/;
            var host = regex.exec(url)[1];
            var socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';

            return socketProtocol + '://' + host;
        }

        function _emitSocketProgress(uploader, progressData, file) {
            var progress = progressData.progress,
                bytesUploaded = progressData.bytesUploaded,
                bytesTotal = progressData.bytesTotal;

            if (progress) {
                uploader.uppy.log('Upload progress: ' + progress);
                uploader.uppy.emit('upload-progress', {
                    uploader: uploader,
                    id: file.id,
                    bytesUploaded: bytesUploaded,
                    bytesTotal: bytesTotal
                });
            }
        }

        var emitSocketProgress = throttle(_emitSocketProgress, 300, { leading: true, trailing: true });

        function settle(promises) {
            var resolutions = [];
            var rejections = [];
            function resolved(value) {
                resolutions.push(value);
            }
            function rejected(error) {
                rejections.push(error);
            }

            var wait = _Promise.all(promises.map(function (promise) {
                return promise.then(resolved, rejected);
            }));

            return wait.then(function () {
                return {
                    successful: resolutions,
                    failed: rejections
                };
            });
        }

        /**
         * Limit the amount of simultaneously pending Promises.
         * Returns a function that, when passed a function `fn`,
         * will make sure that at most `limit` calls to `fn` are pending.
         *
         * @param {number} limit
         * @return {function()}
         */
        function limitPromises(limit) {
            var pending = 0;
            var queue = [];
            return function (fn) {
                return function () {
                    for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
                        args[_key2] = arguments[_key2];
                    }

                    var call = function call() {
                        pending++;
                        var promise = fn.apply(undefined, args);
                        promise.then(onfinish, onfinish);
                        return promise;
                    };

                    if (pending >= limit) {
                        return new _Promise(function (resolve, reject) {
                            queue.push(function () {
                                call().then(resolve, reject);
                            });
                        });
                    }
                    return call();
                };
            };
            function onfinish() {
                pending--;
                var next = queue.shift();
                if (next) next();
            }
        }

        module.exports = {
            generateFileID: generateFileID,
            toArray: toArray,
            getTimeStamp: getTimeStamp,
            runPromiseSequence: runPromiseSequence,
            isTouchDevice: isTouchDevice,
            getFileNameAndExtension: getFileNameAndExtension,
            truncateString: truncateString,
            getFileTypeExtension: getFileTypeExtension,
            getFileType: getFileType,
            getArrayBuffer: getArrayBuffer,
            isPreviewSupported: isPreviewSupported,
            isObjectURL: isObjectURL,
            createThumbnail: createThumbnail,
            secondsToTime: secondsToTime,
            dataURItoBlob: dataURItoBlob,
            dataURItoFile: dataURItoFile,
            canvasToBlob: canvasToBlob,
            getSpeed: getSpeed,
            getBytesRemaining: getBytesRemaining,
            getETA: getETA,
            copyToClipboard: copyToClipboard,
            prettyETA: prettyETA,
            findDOMElement: findDOMElement,
            findAllDOMElements: findAllDOMElements,
            getSocketHost: getSocketHost,
            emitSocketProgress: emitSocketProgress,
            settle: settle,
            limitPromises: limitPromises
        };

    },{"../vendor/file-type":135,"es6-promise":33,"lodash.throttle":40}],78:[function(require,module,exports){
        'use strict';

        var Core = require('./Core');
        module.exports = Core;

    },{"./Core":73}],79:[function(require,module,exports){
        'use strict';

        var Core = require('./core');

// Parent
        var Plugin = require('./core/Plugin');

// Orchestrators
        var Dashboard = require('./plugins/Dashboard');

// Acquirers
        var Dummy = require('./plugins/Dummy');
        var DragDrop = require('./plugins/DragDrop');
        var FileInput = require('./plugins/FileInput');
        var GoogleDrive = require('./plugins/GoogleDrive');
        var Dropbox = require('./plugins/Dropbox');
        var Instagram = require('./plugins/Instagram');
        var Webcam = require('./plugins/Webcam');

// Progressindicators
        var StatusBar = require('./plugins/StatusBar');
        var ProgressBar = require('./plugins/ProgressBar');
        var Informer = require('./plugins/Informer');

// Modifiers

// Uploaders
        var Tus = require('./plugins/Tus');
        var XHRUpload = require('./plugins/XHRUpload');
        var Transloadit = require('./plugins/Transloadit');
        var AwsS3 = require('./plugins/AwsS3');

// Helpers and utilities
        var GoldenRetriever = require('./plugins/GoldenRetriever');
        var ReduxDevTools = require('./plugins/ReduxDevTools');
        var ReduxStore = require('./plugins/Redux');

        module.exports = {
            Core: Core,
            Plugin: Plugin,
            Dummy: Dummy,
            StatusBar: StatusBar,
            ProgressBar: ProgressBar,
            Informer: Informer,
            DragDrop: DragDrop,
            GoogleDrive: GoogleDrive,
            Dropbox: Dropbox,
            Instagram: Instagram,
            FileInput: FileInput,
            Tus: Tus,
            XHRUpload: XHRUpload,
            Transloadit: Transloadit,
            AwsS3: AwsS3,
            Dashboard: Dashboard,
            Webcam: Webcam,
            GoldenRetriever: GoldenRetriever,
            ReduxDevTools: ReduxDevTools,
            ReduxStore: ReduxStore
        };

    },{"./core":78,"./core/Plugin":74,"./plugins/AwsS3":80,"./plugins/Dashboard":90,"./plugins/DragDrop":91,"./plugins/Dropbox":93,"./plugins/Dummy":94,"./plugins/FileInput":95,"./plugins/GoldenRetriever":99,"./plugins/GoogleDrive":100,"./plugins/Informer":101,"./plugins/Instagram":102,"./plugins/ProgressBar":103,"./plugins/Redux":114,"./plugins/ReduxDevTools":115,"./plugins/StatusBar":117,"./plugins/Transloadit":121,"./plugins/Tus":122,"./plugins/Webcam":131,"./plugins/XHRUpload":133}],80:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var Plugin = require('../../core/Plugin');
        var Translator = require('../../core/Translator');

        var _require = require('../../core/Utils'),
            limitPromises = _require.limitPromises;

        var XHRUpload = require('../XHRUpload');

        function isXml(xhr) {
            var contentType = xhr.getResponseHeader('Content-Type');
            return typeof contentType === 'string' && contentType.toLowerCase() === 'application/xml';
        }

        module.exports = function (_Plugin) {
            _inherits(AwsS3, _Plugin);

            function AwsS3(uppy, opts) {
                _classCallCheck(this, AwsS3);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'uploader';
                _this.id = 'AwsS3';
                _this.title = 'AWS S3';

                var defaultLocale = {
                    strings: {
                        preparingUpload: 'Preparing upload...'
                    }
                };

                var defaultOptions = {
                    timeout: 30 * 1000,
                    limit: 0,
                    getUploadParameters: _this.getUploadParameters.bind(_this),
                    locale: defaultLocale
                };

                _this.opts = _extends({}, defaultOptions, opts);
                _this.locale = _extends({}, defaultLocale, _this.opts.locale);
                _this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);

                _this.translator = new Translator({ locale: _this.locale });
                _this.i18n = _this.translator.translate.bind(_this.translator);

                _this.prepareUpload = _this.prepareUpload.bind(_this);

                if (typeof _this.opts.limit === 'number' && _this.opts.limit !== 0) {
                    _this.limitRequests = limitPromises(_this.opts.limit);
                } else {
                    _this.limitRequests = function (fn) {
                        return fn;
                    };
                }
                return _this;
            }

            AwsS3.prototype.getUploadParameters = function getUploadParameters(file) {
                if (!this.opts.host) {
                    throw new Error('Expected a `host` option containing an uppy-server address.');
                }

                var filename = encodeURIComponent(file.name);
                var type = encodeURIComponent(file.type);
                return fetch(this.opts.host + '/s3/params?filename=' + filename + '&type=' + type, {
                    method: 'get',
                    headers: { accept: 'application/json' }
                }).then(function (response) {
                    return response.json();
                });
            };

            AwsS3.prototype.prepareUpload = function prepareUpload(fileIDs) {
                var _this2 = this;

                fileIDs.forEach(function (id) {
                    _this2.uppy.emit('preprocess-progress', id, {
                        mode: 'determinate',
                        message: _this2.i18n('preparingUpload'),
                        value: 0
                    });
                });

                var getUploadParameters = this.limitRequests(this.opts.getUploadParameters);

                return _Promise.all(fileIDs.map(function (id) {
                    var file = _this2.uppy.getFile(id);
                    var paramsPromise = _Promise.resolve().then(function () {
                        return getUploadParameters(file);
                    });
                    return paramsPromise.then(function (params) {
                        _this2.uppy.emit('preprocess-progress', file.id, {
                            mode: 'determinate',
                            message: _this2.i18n('preparingUpload'),
                            value: 1
                        });
                        return params;
                    }).catch(function (error) {
                        _this2.uppy.emit('upload-error', file.id, error);
                    });
                })).then(function (responses) {
                    var updatedFiles = {};
                    fileIDs.forEach(function (id, index) {
                        var file = _this2.uppy.getFile(id);
                        if (file.error) {
                            return;
                        }

                        var _responses$index = responses[index],
                            _responses$index$meth = _responses$index.method,
                            method = _responses$index$meth === undefined ? 'post' : _responses$index$meth,
                            url = _responses$index.url,
                            fields = _responses$index.fields,
                            headers = _responses$index.headers;

                        var xhrOpts = {
                            method: method,
                            formData: method.toLowerCase() === 'post',
                            endpoint: url,
                            metaFields: Object.keys(fields)
                        };

                        if (headers) {
                            xhrOpts.headers = headers;
                        }

                        var updatedFile = _extends({}, file, {
                            meta: _extends({}, file.meta, fields),
                            xhrUpload: xhrOpts
                        });

                        updatedFiles[id] = updatedFile;
                    });

                    _this2.uppy.setState({
                        files: _extends({}, _this2.uppy.getState().files, updatedFiles)
                    });

                    fileIDs.forEach(function (id) {
                        _this2.uppy.emit('preprocess-complete', id);
                    });
                });
            };

            AwsS3.prototype.install = function install() {
                this.uppy.addPreProcessor(this.prepareUpload);

                this.uppy.use(XHRUpload, {
                    fieldName: 'file',
                    responseUrlFieldName: 'location',
                    timeout: this.opts.timeout,
                    limit: this.opts.limit,
                    getResponseData: function getResponseData(xhr) {
                        // If no response, we've hopefully done a PUT request to the file
                        // in the bucket on its full URL.
                        if (!isXml(xhr)) {
                            return { location: xhr.responseURL };
                        }
                        function getValue(key) {
                            var el = xhr.responseXML.querySelector(key);
                            return el ? el.textContent : '';
                        }
                        return {
                            location: getValue('Location'),
                            bucket: getValue('Bucket'),
                            key: getValue('Key'),
                            etag: getValue('ETag')
                        };
                    },
                    getResponseError: function getResponseError(xhr) {
                        // If no response, we don't have a specific error message, use the default.
                        if (!isXml(xhr)) {
                            return;
                        }
                        var error = xhr.responseXML.querySelector('Error > Message');
                        return new Error(error.textContent);
                    }
                });
            };

            AwsS3.prototype.uninstall = function uninstall() {
                var uploader = this.uppy.getPlugin('XHRUpload');
                this.uppy.removePlugin(uploader);

                this.uppy.removePreProcessor(this.prepareUpload);
            };

            return AwsS3;
        }(Plugin);

    },{"../../core/Plugin":74,"../../core/Translator":75,"../../core/Utils":77,"../XHRUpload":133,"es6-promise":33}],81:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _require = require('preact'),
            h = _require.h,
            Component = _require.Component;

        var ActionBrowseTagline = function (_Component) {
            _inherits(ActionBrowseTagline, _Component);

            function ActionBrowseTagline(props) {
                _classCallCheck(this, ActionBrowseTagline);

                var _this = _possibleConstructorReturn(this, _Component.call(this, props));

                _this.handleClick = _this.handleClick.bind(_this);
                return _this;
            }

            ActionBrowseTagline.prototype.handleClick = function handleClick(ev) {
                this.input.click();
            };

            ActionBrowseTagline.prototype.render = function render() {
                var _this2 = this;

                // empty value=""  on file input, so we can select same file
                // after removing it from Uppy â€” otherwise OS thinks itâ€™s selected
                return h(
                    'span',
                    null,
                    this.props.acquirers.length === 0 ? this.props.i18n('dropPaste') : this.props.i18n('dropPasteImport'),
                    ' ',
                    h(
                        'button',
                        { type: 'button', 'class': 'uppy-Dashboard-browse', onclick: this.handleClick },
                        this.props.i18n('browse')
                    ),
                    h('input', { 'class': 'uppy-Dashboard-input',
                        hidden: 'true',
                        'aria-hidden': 'true',
                        tabindex: '-1',
                        type: 'file',
                        name: 'files[]',
                        multiple: 'true',
                        onchange: this.props.handleInputChange,
                        value: '',
                        ref: function ref(input) {
                            _this2.input = input;
                        } })
                );
            };

            return ActionBrowseTagline;
        }(Component);

        module.exports = ActionBrowseTagline;

    },{"preact":46}],82:[function(require,module,exports){
        'use strict';

        var FileList = require('./FileList');
        var Tabs = require('./Tabs');
        var FileCard = require('./FileCard');
        var classNames = require('classnames');

        var _require = require('../../core/Utils'),
            isTouchDevice = _require.isTouchDevice;

        var _require2 = require('./icons'),
            closeIcon = _require2.closeIcon;

        var _require3 = require('preact'),
            h = _require3.h;

// http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
// https://github.com/ghosh/micromodal

        var renderInnerPanel = function renderInnerPanel(props) {
            return h(
                'div',
                { style: { width: '100%', height: '100%' } },
                h(
                    'div',
                    { 'class': 'uppy-DashboardContent-bar' },
                    h(
                        'div',
                        { 'class': 'uppy-DashboardContent-title' },
                        props.i18n('importFrom'),
                        ' ',
                        props.activePanel ? props.activePanel.name : null
                    ),
                    h(
                        'button',
                        { 'class': 'uppy-DashboardContent-back',
                            type: 'button',
                            onclick: props.hideAllPanels },
                        props.i18n('done')
                    )
                ),
                props.getPlugin(props.activePanel.id).render(props.state)
            );
        };

        module.exports = function Dashboard(props) {
            var dashboardClassName = classNames('uppy', 'uppy-Dashboard', { 'Uppy--isTouchDevice': isTouchDevice() }, { 'uppy-Dashboard--modal': !props.inline }, { 'uppy-Dashboard--wide': props.isWide });
            dashboardClassName += ' uppy-thread-' + props.i18n('thread_id');

            return h(
                'div',
                { 'class': dashboardClassName,
                    'aria-hidden': props.inline ? 'false' : props.modal.isHidden,
                    'aria-label': !props.inline ? props.i18n('dashboardWindowTitle') : props.i18n('dashboardTitle'),
                    'data-thread-id' : props.i18n('thread_id'),
                    onpaste: props.handlePaste },
                h('div', { 'class': 'uppy-Dashboard-overlay', tabindex: '-1', onclick: props.handleClickOutside }),
                h(
                    'div',
                    { 'class': 'uppy-Dashboard-inner',
                        'aria-modal': !props.inline && 'true',
                        role: !props.inline && 'dialog',
                        style: {
                            maxWidth: props.inline && props.maxWidth ? props.maxWidth : '',
                            maxHeight: props.inline && props.maxHeight ? props.maxHeight : ''
                        } },
                    h(
                        'button',
                        { 'class': 'uppy-Dashboard-close',
                            type: 'button',
                            'aria-label': props.i18n('closeModal'),
                            title: props.i18n('closeModal'),
                            onclick: props.closeModal },
                        closeIcon()
                    ),
                    h(
                        'div',
                        { 'class': 'uppy-Dashboard-innerWrap' },
                        h(Tabs, props),
                        h(FileCard, props),
                        h(
                            'div',
                            { 'class': 'uppy-Dashboard-filesContainer' },
                            h(FileList, props)
                        ),
                        h(
                            'div',
                            { 'class': 'uppy-DashboardContent-panel',
                                role: 'tabpanel',
                                id: props.activePanel && 'uppy-DashboardContent-panel--' + props.activePanel.id,
                                'aria-hidden': props.activePanel ? 'false' : 'true' },
                            props.activePanel && renderInnerPanel(props)
                        ),
                        h(
                            'span',
                            {
                                'class': 'bpbm-send-files bpbm-button'
                            },
                            props.i18n('send_files')
                        ),
                        h(
                            'div',
                            { 'class': 'uppy-Dashboard-progressindicators' },
                            props.progressindicators.map(function (target) {
                                return props.getPlugin(target.id).render(props.state);
                            })
                        )
                    )
                )
            );
        };

    },{"../../core/Utils":77,"./FileCard":83,"./FileList":86,"./Tabs":87,"./icons":89,"classnames":7,"preact":46}],83:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var getFileTypeIcon = require('./getFileTypeIcon');

        var _require = require('./icons'),
            checkIcon = _require.checkIcon;

        var _require2 = require('preact'),
            h = _require2.h,
            Component = _require2.Component;

        module.exports = function (_Component) {
            _inherits(FileCard, _Component);

            function FileCard(props) {
                _classCallCheck(this, FileCard);

                var _this = _possibleConstructorReturn(this, _Component.call(this, props));

                _this.meta = {};

                _this.tempStoreMetaOrSubmit = _this.tempStoreMetaOrSubmit.bind(_this);
                _this.renderMetaFields = _this.renderMetaFields.bind(_this);
                _this.handleClick = _this.handleClick.bind(_this);
                return _this;
            }

            FileCard.prototype.tempStoreMetaOrSubmit = function tempStoreMetaOrSubmit(ev) {
                var file = this.props.files[this.props.fileCardFor];

                if (ev.keyCode === 13) {
                    ev.stopPropagation();
                    ev.preventDefault();
                    this.props.fileCardDone(this.meta, file.id);
                    return;
                }

                var value = ev.target.value;
                var name = ev.target.dataset.name;
                this.meta[name] = value;
            };

            FileCard.prototype.renderMetaFields = function renderMetaFields(file) {
                var _this2 = this;

                var metaFields = this.props.metaFields || [];
                return metaFields.map(function (field) {
                    return h(
                        'fieldset',
                        { 'class': 'uppy-DashboardFileCard-fieldset' },
                        h(
                            'label',
                            { 'class': 'uppy-DashboardFileCard-label' },
                            field.name
                        ),
                        h('input', { 'class': 'uppy-DashboardFileCard-input',
                            type: 'text',
                            'data-name': field.id,
                            value: file.meta[field.id],
                            placeholder: field.placeholder,
                            onkeyup: _this2.tempStoreMetaOrSubmit,
                            onkeydown: _this2.tempStoreMetaOrSubmit,
                            onkeypress: _this2.tempStoreMetaOrSubmit })
                    );
                });
            };

            FileCard.prototype.handleClick = function handleClick(ev) {
                var file = this.props.files[this.props.fileCardFor];
                this.props.fileCardDone(this.meta, file.id);
            };

            FileCard.prototype.render = function render() {
                var file = this.props.files[this.props.fileCardFor];

                return h(
                    'div',
                    { 'class': 'uppy-DashboardFileCard', 'aria-hidden': !this.props.fileCardFor },
                    this.props.fileCardFor && h(
                    'div',
                    { style: 'width: 100%; height: 100%;' },
                    h(
                        'div',
                        { 'class': 'uppy-DashboardContent-bar' },
                        h(
                            'h2',
                            { 'class': 'uppy-DashboardContent-title' },
                            this.props.i18n('editing'),
                            ' ',
                            h(
                                'span',
                                { 'class': 'uppy-DashboardContent-titleFile' },
                                file.meta ? file.meta.name : file.name
                            )
                        ),
                        h(
                            'button',
                            { 'class': 'uppy-DashboardContent-back', type: 'button', title: this.props.i18n('finishEditingFile'),
                                onclick: this.handleClick },
                            this.props.i18n('done')
                        )
                    ),
                    h(
                        'div',
                        { 'class': 'uppy-DashboardFileCard-inner' },
                        h(
                            'div',
                            { 'class': 'uppy-DashboardFileCard-preview', style: { backgroundColor: getFileTypeIcon(file.type).color } },
                            file.preview ? h('img', { alt: file.name, src: file.preview }) : h(
                                'div',
                                { 'class': 'uppy-DashboardItem-previewIconWrap' },
                                h(
                                    'span',
                                    { 'class': 'uppy-DashboardItem-previewIcon', style: { color: getFileTypeIcon(file.type).color } },
                                    getFileTypeIcon(file.type).icon
                                ),
                                h(
                                    'svg',
                                    { 'class': 'uppy-DashboardItem-previewIconBg', width: '72', height: '93', viewBox: '0 0 72 93' },
                                    h(
                                        'g',
                                        null,
                                        h('path', { d: 'M24.08 5h38.922A2.997 2.997 0 0 1 66 8.003v74.994A2.997 2.997 0 0 1 63.004 86H8.996A2.998 2.998 0 0 1 6 83.01V22.234L24.08 5z', fill: '#FFF' }),
                                        h('path', { d: 'M24 5L6 22.248h15.007A2.995 2.995 0 0 0 24 19.244V5z', fill: '#E4E4E4' })
                                    )
                                )
                            )
                        ),
                        h(
                            'div',
                            { 'class': 'uppy-DashboardFileCard-info' },
                            h(
                                'fieldset',
                                { 'class': 'uppy-DashboardFileCard-fieldset' },
                                h(
                                    'label',
                                    { 'class': 'uppy-DashboardFileCard-label' },
                                    this.props.i18n('name')
                                ),
                                h('input', { 'class': 'uppy-DashboardFileCard-input',
                                    type: 'text',
                                    'data-name': 'name',
                                    value: file.meta.name || '',
                                    placeholder: this.props.i18n('name'),
                                    onkeyup: this.tempStoreMetaOrSubmit,
                                    onkeydown: this.tempStoreMetaOrSubmit,
                                    onkeypress: this.tempStoreMetaOrSubmit })
                            ),
                            this.renderMetaFields(file)
                        )
                    ),
                    h(
                        'div',
                        { 'class': 'uppy-Dashboard-actions' },
                        h(
                            'button',
                            { 'class': 'UppyButton--circular UppyButton--blue uppy-DashboardFileCard-done',
                                type: 'button',
                                title: this.props.i18n('finishEditingFiles'),
                                onclick: this.handleClick },
                            checkIcon()
                        )
                    )
                    )
                );
            };

            return FileCard;
        }(Component);

    },{"./getFileTypeIcon":88,"./icons":89,"preact":46}],84:[function(require,module,exports){
        'use strict';

        var _require = require('../../core/Utils'),
            getETA = _require.getETA,
            getSpeed = _require.getSpeed,
            prettyETA = _require.prettyETA,
            getFileNameAndExtension = _require.getFileNameAndExtension,
            truncateString = _require.truncateString,
            copyToClipboard = _require.copyToClipboard;

        var prettyBytes = require('prettier-bytes');
        var FileItemProgress = require('./FileItemProgress');
        var getFileTypeIcon = require('./getFileTypeIcon');

        var _require2 = require('./icons'),
            iconEdit = _require2.iconEdit,
            iconCopy = _require2.iconCopy,
            iconRetry = _require2.iconRetry;

        var classNames = require('classnames');

        var _require3 = require('preact'),
            h = _require3.h;

        module.exports = function fileItem(props) {
            var file = props.file;
            var acquirers = props.acquirers;

            var isProcessing = file.progress.preprocess || file.progress.postprocess;
            var isUploaded = file.progress.uploadComplete && !isProcessing && !file.error;
            var uploadInProgressOrComplete = file.progress.uploadStarted || isProcessing;
            var uploadInProgress = file.progress.uploadStarted && !file.progress.uploadComplete || isProcessing;
            var isPaused = file.isPaused || false;
            var error = file.error || false;

            var fileName = getFileNameAndExtension(file.meta.name).name;
            var truncatedFileName = props.isWide ? truncateString(fileName, 14) : fileName;

            var onPauseResumeCancelRetry = function onPauseResumeCancelRetry(ev) {
                if (isUploaded) return;
                if (error) {
                    props.retryUpload(file.id);
                    return;
                }
                if (props.resumableUploads) {
                    props.pauseUpload(file.id);
                } else {
                    props.cancelUpload(file.id);
                }
            };

            var dashboardItemClass = classNames('uppy-DashboardItem', { 'is-inprogress': uploadInProgress }, { 'is-processing': isProcessing },     { 'is-paused': isPaused }, { 'is-error': error }, { 'is-resumable': props.resumableUploads });

            return h(
                'li',
                { 'class': dashboardItemClass, id: 'uppy_' + file.id, title: file.meta.name },
                h(
                    'div',
                    { 'class': 'uppy-DashboardItem-preview' },
                    h(
                        'div',
                        { 'class': 'uppy-DashboardItem-previewInnerWrap', style: { backgroundColor: getFileTypeIcon(file.type).color } },
                        file.preview ? h('img', { alt: file.name, src: file.preview }) : h(
                            'div',
                            { 'class': 'uppy-DashboardItem-previewIconWrap' },
                            h(
                                'span',
                                { 'class': 'uppy-DashboardItem-previewIcon', style: { color: getFileTypeIcon(file.type).color } },
                                getFileTypeIcon(file.type).icon
                            ),
                            h(
                                'svg',
                                { 'class': 'uppy-DashboardItem-previewIconBg', width: '72', height: '93', viewBox: '0 0 72 93' },
                                h(
                                    'g',
                                    null,
                                    h('path', { d: 'M24.08 5h38.922A2.997 2.997 0 0 1 66 8.003v74.994A2.997 2.997 0 0 1 63.004 86H8.996A2.998 2.998 0 0 1 6 83.01V22.234L24.08 5z', fill: '#FFF' }),
                                    h('path', { d: 'M24 5L6 22.248h15.007A2.995 2.995 0 0 0 24 19.244V5z', fill: '#E4E4E4' })
                                )
                            )
                        )
                    ),
                    h(
                        'div',
                        { 'class': 'uppy-DashboardItem-progress' },
                        isUploaded ? h(
                            'div',
                            { 'class': 'uppy-DashboardItem-progressIndicator' },
                            FileItemProgress({
                                progress: file.progress.percentage,
                                fileID: file.id
                            })
                        ) : h(
                            'button',
                            { 'class': 'uppy-DashboardItem-progressIndicator',
                                type: 'button',
                                title: isUploaded ? 'upload complete' : props.resumableUploads ? file.isPaused ? 'resume upload' : 'pause upload' : 'cancel upload',
                                onclick: onPauseResumeCancelRetry },
                            error ? iconRetry() : FileItemProgress({
                                progress: file.progress.percentage,
                                fileID: file.id
                            })
                        ),
                        props.showProgressDetails && h(
                        'div',
                        { 'class': 'uppy-DashboardItem-progressInfo',
                            title: props.i18n('fileProgress'),
                            'aria-label': props.i18n('fileProgress') },
                        !file.isPaused && !isUploaded && h(
                        'span',
                        null,
                        prettyETA(getETA(file.progress)),
                        ' \u30FB \u2191 ',
                        prettyBytes(getSpeed(file.progress)),
                        '/s'
                        )
                        )
                    )
                ),
                h(
                    'div',
                    { 'class': 'uppy-DashboardItem-info' },
                    h(
                        'h4',
                        { 'class': 'uppy-DashboardItem-name', title: fileName },
                        file.uploadURL ? h(
                            'a',
                            { href: file.uploadURL, target: '_blank' },
                            file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName
                        ) : file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName
                    ),
                    h(
                        'div',
                        { 'class': 'uppy-DashboardItem-status' },
                        file.data.size && h(
                        'div',
                        { 'class': 'uppy-DashboardItem-statusSize' },
                        prettyBytes(file.data.size)
                        ),
                        file.source && h(
                        'div',
                        { 'class': 'uppy-DashboardItem-sourceIcon' },
                        acquirers.map(function (acquirer) {
                            if (acquirer.id === file.source) return h(
                                'span',
                                { title: props.i18n('fileSource') + ': ' + acquirer.name },
                                acquirer.icon()
                            );
                        })
                        )
                    ),
                    !uploadInProgressOrComplete && h(
                    'button',
                    { 'class': 'uppy-DashboardItem-edit',
                        type: 'button',
                        'aria-label': props.i18n('editFile'),
                        title: props.i18n('editFile'),
                        onclick: function onclick(e) {
                            return props.showFileCard(file.id);
                        } },
                    iconEdit()
                    ),
                    file.uploadURL && h(
                    'button',
                    { 'class': 'uppy-DashboardItem-copyLink',
                        type: 'button',
                        'aria-label': props.i18n('copyLink'),
                        title: props.i18n('copyLink'),
                        onclick: function onclick() {
                            copyToClipboard(file.uploadURL, props.i18n('copyLinkToClipboardFallback')).then(function () {
                                props.log('Link copied to clipboard.');
                                props.info(props.i18n('copyLinkToClipboardSuccess'), 'info', 3000);
                            }).catch(props.log);
                        } },
                    iconCopy()
                    )
                ),
                h(
                    'div',
                    { 'class': 'uppy-DashboardItem-action' },
                    h(
                    'button',
                    { 'class': 'uppy-DashboardItem-remove',
                        type: 'button',
                        'aria-label': props.i18n('removeFile'),
                        title: props.i18n('removeFile'),
                        onclick: function onclick() {
                            return props.removeFile(file.id);
                        } },
                    h(
                        'svg',
                        { 'aria-hidden': 'true', 'class': 'UppyIcon', width: '60', height: '60', viewBox: '0 0 60 60', xmlns: 'http://www.w3.org/2000/svg' },
                        h('path', { stroke: '#FFF', 'stroke-width': '1', 'fill-rule': 'nonzero', 'vector-effect': 'non-scaling-stroke', d: 'M30 1C14 1 1 14 1 30s13 29 29 29 29-13 29-29S46 1 30 1z' }),
                        h('path', { fill: '#FFF', 'vector-effect': 'non-scaling-stroke', d: 'M42 39.667L39.667 42 30 32.333 20.333 42 18 39.667 27.667 30 18 20.333 20.333 18 30 27.667 39.667 18 42 20.333 32.333 30z' })
                    )
                    )
                )
            );
        };

    },{"../../core/Utils":77,"./FileItemProgress":85,"./getFileTypeIcon":88,"./icons":89,"classnames":7,"preact":46,"prettier-bytes":47}],85:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

// http://codepen.io/Harkko/pen/rVxvNM
// https://css-tricks.com/svg-line-animation-works/
// https://gist.github.com/eswak/ad4ea57bcd5ff7aa5d42

// circle length equals 2 * PI * R


        var circleLength = 2 * Math.PI * 15;

// stroke-dashoffset is a percentage of the progress from circleLength,
// substracted from circleLength, because its an offset
        module.exports = function (props) {
            return h(
                "svg",
                { width: "70", height: "70", viewBox: "0 0 36 36", "class": "UppyIcon UppyIcon-progressCircle" },
                h(
                    "g",
                    { "class": "progress-group" },
                    h("circle", { r: "15", cx: "18", cy: "18", "stroke-width": "2", fill: "none", "class": "bg" }),
                    h("circle", { r: "15", cx: "18", cy: "18", transform: "rotate(-90, 18, 18)", "stroke-width": "2", fill: "none", "class": "progress",
                        "stroke-dasharray": circleLength,
                        "stroke-dashoffset": circleLength - circleLength / 100 * props.progress
                    })
                ),
                h("polygon", { transform: "translate(3, 3)", points: "12 20 12 10 20 15", "class": "play" }),
                h(
                    "g",
                    { transform: "translate(14.5, 13)", "class": "pause" },
                    h("rect", { x: "0", y: "0", width: "2", height: "10", rx: "0" }),
                    h("rect", { x: "5", y: "0", width: "2", height: "10", rx: "0" })
                ),
                h("polygon", { transform: "translate(2, 3)", points: "14 22.5 7 15.2457065 8.99985857 13.1732815 14 18.3547104 22.9729883 9 25 11.1005634", "class": "check" }),
                h("polygon", { "class": "cancel", transform: "translate(2, 2)", points: "19.8856516 11.0625 16 14.9481516 12.1019737 11.0625 11.0625 12.1143484 14.9481516 16 11.0625 19.8980263 12.1019737 20.9375 16 17.0518484 19.8856516 20.9375 20.9375 19.8980263 17.0518484 16 20.9375 12" })
            );
        };

    },{"preact":46}],86:[function(require,module,exports){
        'use strict';

        var FileItem = require('./FileItem');
        var ActionBrowseTagline = require('./ActionBrowseTagline');

        var _require = require('./icons'),
            dashboardBgIcon = _require.dashboardBgIcon;

        var classNames = require('classnames');

        var _require2 = require('preact'),
            h = _require2.h;

        module.exports = function (props) {
            var noFiles = props.totalFileCount === 0;
            var dashboardFilesClass = classNames('uppy-Dashboard-files', { 'uppy-Dashboard-files--noFiles': noFiles });

            return h(
                'ul',
                { 'class': dashboardFilesClass },
                noFiles && h(
                'div',
                { 'class': 'uppy-Dashboard-bgIcon' },
                dashboardBgIcon(),
                h(
                    'h3',
                    { 'class': 'uppy-Dashboard-dropFilesTitle' },
                    h(ActionBrowseTagline, {
                        acquirers: props.acquirers,
                        handleInputChange: props.handleInputChange,
                        i18n: props.i18n
                    })
                ),
                props.note && h(
                'p',
                { 'class': 'uppy-Dashboard-note' },
                props.note
                )
                ),
                Object.keys(props.files).map(function (fileID) {
                    return FileItem({
                        acquirers: props.acquirers,
                        file: props.files[fileID],
                        showFileCard: props.showFileCard,
                        showProgressDetails: props.showProgressDetails,
                        info: props.info,
                        log: props.log,
                        i18n: props.i18n,
                        removeFile: props.removeFile,
                        pauseUpload: props.pauseUpload,
                        cancelUpload: props.cancelUpload,
                        retryUpload: props.retryUpload,
                        resumableUploads: props.resumableUploads,
                        isWide: props.isWide
                    });
                })
            );
        };

    },{"./ActionBrowseTagline":81,"./FileItem":84,"./icons":89,"classnames":7,"preact":46}],87:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var ActionBrowseTagline = require('./ActionBrowseTagline');

        var _require = require('./icons'),
            localIcon = _require.localIcon;

        var _require2 = require('preact'),
            h = _require2.h,
            Component = _require2.Component;

        var Tabs = function (_Component) {
            _inherits(Tabs, _Component);

            function Tabs(props) {
                _classCallCheck(this, Tabs);

                var _this = _possibleConstructorReturn(this, _Component.call(this, props));

                _this.handleClick = _this.handleClick.bind(_this);
                return _this;
            }

            Tabs.prototype.handleClick = function handleClick(ev) {
                this.input.click();
            };

            Tabs.prototype.render = function render() {
                var _this2 = this;

                var isHidden = Object.keys(this.props.files).length === 0;
                var hasAcquirers = this.props.acquirers.length !== 0;

                if (!hasAcquirers) {
                    return h(
                        'div',
                        { 'class': 'uppy-DashboardTabs', 'aria-hidden': isHidden },
                        h(
                            'div',
                            { 'class': 'uppy-DashboardTabs-title' },
                            h(ActionBrowseTagline, {
                                acquirers: this.props.acquirers,
                                handleInputChange: this.props.handleInputChange,
                                i18n: this.props.i18n })
                        )
                    );
                }

                // empty value=""  on file input, so we can select same file
                // after removing it from Uppy â€” otherwise OS thinks itâ€™s selected

                return h(
                    'div',
                    { 'class': 'uppy-DashboardTabs' },
                    h(
                        'ul',
                        { 'class': 'uppy-DashboardTabs-list', role: 'tablist' },
                        h(
                            'li',
                            { 'class': 'uppy-DashboardTab', role: 'presentation' },
                            h(
                                'button',
                                { type: 'button',
                                    'class': 'uppy-DashboardTab-btn',
                                    role: 'tab',
                                    tabindex: '0',
                                    onclick: this.handleClick },
                                localIcon(),
                                h(
                                    'div',
                                    { 'class': 'uppy-DashboardTab-name' },
                                    this.props.i18n('myDevice')
                                )
                            ),
                            h('input', { 'class': 'uppy-Dashboard-input',
                                hidden: 'true',
                                'aria-hidden': 'true',
                                tabindex: '-1',
                                type: 'file',
                                name: 'files[]',
                                multiple: 'true',
                                onchange: this.props.handleInputChange,
                                value: '',
                                ref: function ref(input) {
                                    _this2.input = input;
                                } })
                        ),
                        this.props.acquirers.map(function (target) {
                            return h(
                                'li',
                                { 'class': 'uppy-DashboardTab', role: 'presentation' },
                                h(
                                    'button',
                                    { 'class': 'uppy-DashboardTab-btn',
                                        type: 'button',
                                        role: 'tab',
                                        tabindex: '0',
                                        'aria-controls': 'uppy-DashboardContent-panel--' + target.id,
                                        'aria-selected': _this2.props.activePanel.id === target.id,
                                        onclick: function onclick() {
                                            return _this2.props.showPanel(target.id);
                                        } },
                                    target.icon(),
                                    h(
                                        'h5',
                                        { 'class': 'uppy-DashboardTab-name' },
                                        target.name
                                    )
                                )
                            );
                        })
                    )
                );
            };

            return Tabs;
        }(Component);

        module.exports = Tabs;

    },{"./ActionBrowseTagline":81,"./icons":89,"preact":46}],88:[function(require,module,exports){
        'use strict';

        var _require = require('./icons'),
            iconText = _require.iconText,
            iconAudio = _require.iconAudio,
            iconVideo = _require.iconVideo,
            iconPDF = _require.iconPDF;

        module.exports = function getIconByMime(fileType) {
            var defaultChoice = {
                color: '#cbcbcb',
                icon: ''
            };

            if (!fileType) return defaultChoice;

            var fileTypeGeneral = fileType.split('/')[0];
            var fileTypeSpecific = fileType.split('/')[1];

            if (fileTypeGeneral === 'text') {
                return {
                    color: '#cbcbcb',
                    icon: iconText()
                };
            }

            if (fileTypeGeneral === 'audio') {
                return {
                    color: '#1abc9c',
                    icon: iconAudio()
                };
            }

            if (fileTypeGeneral === 'video') {
                return {
                    color: '#2980b9',
                    icon: iconVideo()
                };
            }

            if (fileTypeGeneral === 'application' && fileTypeSpecific === 'pdf') {
                return {
                    color: '#e74c3c',
                    icon: iconPDF()
                };
            }

            if (fileTypeGeneral === 'image') {
                return {
                    color: '#f2f2f2',
                    icon: ''
                };
            }

            return defaultChoice;
        };

    },{"./icons":89}],89:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

// https://css-tricks.com/creating-svg-icon-system-react/

        function defaultTabIcon() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "30", height: "30", viewBox: "0 0 30 30" },
                h("path", { d: "M15 30c8.284 0 15-6.716 15-15 0-8.284-6.716-15-15-15C6.716 0 0 6.716 0 15c0 8.284 6.716 15 15 15zm4.258-12.676v6.846h-8.426v-6.846H5.204l9.82-12.364 9.82 12.364H19.26z" })
            );
        }

        function iconCopy() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "51", height: "51", viewBox: "0 0 51 51" },
                h("path", { d: "M17.21 45.765a5.394 5.394 0 0 1-7.62 0l-4.12-4.122a5.393 5.393 0 0 1 0-7.618l6.774-6.775-2.404-2.404-6.775 6.776c-3.424 3.427-3.424 9 0 12.426l4.12 4.123a8.766 8.766 0 0 0 6.216 2.57c2.25 0 4.5-.858 6.214-2.57l13.55-13.552a8.72 8.72 0 0 0 2.575-6.213 8.73 8.73 0 0 0-2.575-6.213l-4.123-4.12-2.404 2.404 4.123 4.12a5.352 5.352 0 0 1 1.58 3.81c0 1.438-.562 2.79-1.58 3.808l-13.55 13.55z" }),
                h("path", { d: "M44.256 2.858A8.728 8.728 0 0 0 38.043.283h-.002a8.73 8.73 0 0 0-6.212 2.574l-13.55 13.55a8.725 8.725 0 0 0-2.575 6.214 8.73 8.73 0 0 0 2.574 6.216l4.12 4.12 2.405-2.403-4.12-4.12a5.357 5.357 0 0 1-1.58-3.812c0-1.437.562-2.79 1.58-3.808l13.55-13.55a5.348 5.348 0 0 1 3.81-1.58c1.44 0 2.792.562 3.81 1.58l4.12 4.12c2.1 2.1 2.1 5.518 0 7.617L39.2 23.775l2.404 2.404 6.775-6.777c3.426-3.427 3.426-9 0-12.426l-4.12-4.12z" })
            );
        }

        function iconResume() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "25", height: "25", viewBox: "0 0 44 44" },
                h("polygon", { "class": "play", transform: "translate(6, 5.5)", points: "13 21.6666667 13 11 21 16.3333333" })
            );
        }

        function iconPause() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "25px", height: "25px", viewBox: "0 0 44 44" },
                h(
                    "g",
                    { transform: "translate(18, 17)", "class": "pause" },
                    h("rect", { x: "0", y: "0", width: "2", height: "10", rx: "0" }),
                    h("rect", { x: "6", y: "0", width: "2", height: "10", rx: "0" })
                )
            );
        }

        function iconEdit() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "28", height: "28", viewBox: "0 0 28 28" },
                h("path", { d: "M25.436 2.566a7.98 7.98 0 0 0-2.078-1.51C22.638.703 21.906.5 21.198.5a3 3 0 0 0-1.023.17 2.436 2.436 0 0 0-.893.562L2.292 18.217.5 27.5l9.28-1.796 16.99-16.99c.255-.254.444-.56.562-.888a3 3 0 0 0 .17-1.023c0-.708-.205-1.44-.555-2.16a8 8 0 0 0-1.51-2.077zM9.01 24.252l-4.313.834c0-.03.008-.06.012-.09.007-.944-.74-1.715-1.67-1.723-.04 0-.078.007-.118.01l.83-4.29L17.72 5.024l5.264 5.264L9.01 24.252zm16.84-16.96a.818.818 0 0 1-.194.31l-1.57 1.57-5.26-5.26 1.57-1.57a.82.82 0 0 1 .31-.194 1.45 1.45 0 0 1 .492-.074c.397 0 .917.126 1.468.397.55.27 1.13.678 1.656 1.21.53.53.94 1.11 1.208 1.655.272.55.397 1.07.393 1.468.004.193-.027.358-.074.488z" })
            );
        }

        function localIcon() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "27", height: "25", viewBox: "0 0 27 25" },
                h("path", { d: "M5.586 9.288a.313.313 0 0 0 .282.176h4.84v3.922c0 1.514 1.25 2.24 2.792 2.24 1.54 0 2.79-.726 2.79-2.24V9.464h4.84c.122 0 .23-.068.284-.176a.304.304 0 0 0-.046-.324L13.735.106a.316.316 0 0 0-.472 0l-7.63 8.857a.302.302 0 0 0-.047.325z" }),
                h("path", { d: "M24.3 5.093c-.218-.76-.54-1.187-1.208-1.187h-4.856l1.018 1.18h3.948l2.043 11.038h-7.193v2.728H9.114v-2.725h-7.36l2.66-11.04h3.33l1.018-1.18H3.907c-.668 0-1.06.46-1.21 1.186L0 16.456v7.062C0 24.338.676 25 1.51 25h23.98c.833 0 1.51-.663 1.51-1.482v-7.062L24.3 5.093z" })
            );
        }

        function closeIcon() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "14px", height: "14px", viewBox: "0 0 19 19" },
                h("path", { d: "M17.318 17.232L9.94 9.854 9.586 9.5l-.354.354-7.378 7.378h.707l-.62-.62v.706L9.318 9.94l.354-.354-.354-.354L1.94 1.854v.707l.62-.62h-.706l7.378 7.378.354.354.354-.354 7.378-7.378h-.707l.622.62v-.706L9.854 9.232l-.354.354.354.354 7.378 7.378.708-.707-7.38-7.378v.708l7.38-7.38.353-.353-.353-.353-.622-.622-.353-.353-.354.352-7.378 7.38h.708L2.56 1.23 2.208.88l-.353.353-.622.62-.353.355.352.353 7.38 7.38v-.708l-7.38 7.38-.353.353.352.353.622.622.353.353.354-.353 7.38-7.38h-.708l7.38 7.38z" })
            );
        }

        function iconRetry() {
            return h(
                "svg",
                { "class": "UppyIcon retry", width: "28", height: "31", viewBox: "0 0 16 19", xmlns: "http://www.w3.org/2000/svg" },
                h("path", { d: "M16 11a8 8 0 1 1-8-8v2a6 6 0 1 0 6 6h2z" }),
                h("path", { d: "M7.9 3H10v2H7.9z" }),
                h("path", { d: "M8.536.5l3.535 3.536-1.414 1.414L7.12 1.914z" }),
                h("path", { d: "M10.657 2.621l1.414 1.415L8.536 7.57 7.12 6.157z" })
            );
        }

        function pluginIcon() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "16px", height: "16px", viewBox: "0 0 32 30" },
                h("path", { d: "M6.6209894,11.1451162 C6.6823051,11.2751669 6.81374248,11.3572188 6.95463813,11.3572188 L12.6925482,11.3572188 L12.6925482,16.0630427 C12.6925482,17.880509 14.1726048,18.75 16.0000083,18.75 C17.8261072,18.75 19.3074684,17.8801847 19.3074684,16.0630427 L19.3074684,11.3572188 L25.0437478,11.3572188 C25.1875787,11.3572188 25.3164069,11.2751669 25.3790272,11.1451162 C25.4370814,11.0173358 25.4171865,10.8642587 25.3252129,10.7562615 L16.278212,0.127131837 C16.2093949,0.0463771751 16.1069846,0 15.9996822,0 C15.8910751,0 15.7886648,0.0463771751 15.718217,0.127131837 L6.6761083,10.7559371 C6.58250402,10.8642587 6.56293518,11.0173358 6.6209894,11.1451162 L6.6209894,11.1451162 Z" }),
                h("path", { d: "M28.8008722,6.11142645 C28.5417891,5.19831555 28.1583331,4.6875 27.3684848,4.6875 L21.6124454,4.6875 L22.8190234,6.10307874 L27.4986725,6.10307874 L29.9195817,19.3486449 L21.3943891,19.3502502 L21.3943891,22.622552 L10.8023461,22.622552 L10.8023461,19.3524977 L2.07815702,19.3534609 L5.22979699,6.10307874 L9.17871529,6.10307874 L10.3840011,4.6875 L4.6308691,4.6875 C3.83940559,4.6875 3.37421888,5.2390909 3.19815864,6.11142645 L0,19.7470874 L0,28.2212959 C0,29.2043992 0.801477937,30 1.78870751,30 L30.2096773,30 C31.198199,30 32,29.2043992 32,28.2212959 L32,19.7470874 L28.8008722,6.11142645 L28.8008722,6.11142645 Z" })
            );
        }

        function checkIcon() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon UppyIcon-check", width: "13px", height: "9px", viewBox: "0 0 13 9" },
                h("polygon", { points: "5 7.293 1.354 3.647 0.646 4.354 5 8.707 12.354 1.354 11.646 0.647" })
            );
        }

        function iconAudio() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", viewBox: "0 0 55 55" },
                h("path", { d: "M52.66.25c-.216-.19-.5-.276-.79-.242l-31 4.01a1 1 0 0 0-.87.992V40.622C18.174 38.428 15.273 37 12 37c-5.514 0-10 4.037-10 9s4.486 9 10 9 10-4.037 10-9c0-.232-.02-.46-.04-.687.014-.065.04-.124.04-.192V16.12l29-3.753v18.257C49.174 28.428 46.273 27 43 27c-5.514 0-10 4.037-10 9s4.486 9 10 9c5.464 0 9.913-3.966 9.993-8.867 0-.013.007-.024.007-.037V1a.998.998 0 0 0-.34-.75zM12 53c-4.41 0-8-3.14-8-7s3.59-7 8-7 8 3.14 8 7-3.59 7-8 7zm31-10c-4.41 0-8-3.14-8-7s3.59-7 8-7 8 3.14 8 7-3.59 7-8 7zM22 14.1V5.89l29-3.753v8.21l-29 3.754z" })
            );
        }

        function iconVideo() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", viewBox: "0 0 58 58" },
                h("path", { d: "M36.537 28.156l-11-7a1.005 1.005 0 0 0-1.02-.033C24.2 21.3 24 21.635 24 22v14a1 1 0 0 0 1.537.844l11-7a1.002 1.002 0 0 0 0-1.688zM26 34.18V23.82L34.137 29 26 34.18z" }),
                h("path", { d: "M57 6H1a1 1 0 0 0-1 1v44a1 1 0 0 0 1 1h56a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1zM10 28H2v-9h8v9zm-8 2h8v9H2v-9zm10 10V8h34v42H12V40zm44-12h-8v-9h8v9zm-8 2h8v9h-8v-9zm8-22v9h-8V8h8zM2 8h8v9H2V8zm0 42v-9h8v9H2zm54 0h-8v-9h8v9z" })
            );
        }

        function iconPDF() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", viewBox: "0 0 342 335" },
                h("path", { d: "M329.337 227.84c-2.1 1.3-8.1 2.1-11.9 2.1-12.4 0-27.6-5.7-49.1-14.9 8.3-.6 15.8-.9 22.6-.9 12.4 0 16 0 28.2 3.1 12.1 3 12.2 9.3 10.2 10.6zm-215.1 1.9c4.8-8.4 9.7-17.3 14.7-26.8 12.2-23.1 20-41.3 25.7-56.2 11.5 20.9 25.8 38.6 42.5 52.8 2.1 1.8 4.3 3.5 6.7 5.3-34.1 6.8-63.6 15-89.6 24.9zm39.8-218.9c6.8 0 10.7 17.06 11 33.16.3 16-3.4 27.2-8.1 35.6-3.9-12.4-5.7-31.8-5.7-44.5 0 0-.3-24.26 2.8-24.26zm-133.4 307.2c3.9-10.5 19.1-31.3 41.6-49.8 1.4-1.1 4.9-4.4 8.1-7.4-23.5 37.6-39.3 52.5-49.7 57.2zm315.2-112.3c-6.8-6.7-22-10.2-45-10.5-15.6-.2-34.3 1.2-54.1 3.9-8.8-5.1-17.9-10.6-25.1-17.3-19.2-18-35.2-42.9-45.2-70.3.6-2.6 1.2-4.8 1.7-7.1 0 0 10.8-61.5 7.9-82.3-.4-2.9-.6-3.7-1.4-5.9l-.9-2.5c-2.9-6.76-8.7-13.96-17.8-13.57l-5.3-.17h-.1c-10.1 0-18.4 5.17-20.5 12.84-6.6 24.3.2 60.5 12.5 107.4l-3.2 7.7c-8.8 21.4-19.8 43-29.5 62l-1.3 2.5c-10.2 20-19.5 37-27.9 51.4l-8.7 4.6c-.6.4-15.5 8.2-19 10.3-29.6 17.7-49.28 37.8-52.54 53.8-1.04 5-.26 11.5 5.01 14.6l8.4 4.2c3.63 1.8 7.53 2.7 11.43 2.7 21.1 0 45.6-26.2 79.3-85.1 39-12.7 83.4-23.3 122.3-29.1 29.6 16.7 66 28.3 89 28.3 4.1 0 7.6-.4 10.5-1.2 4.4-1.1 8.1-3.6 10.4-7.1 4.4-6.7 5.4-15.9 4.1-25.4-.3-2.8-2.6-6.3-5-8.7z" })
            );
        }

        function iconFile() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "44", height: "58", viewBox: "0 0 44 58" },
                h("path", { d: "M27.437.517a1 1 0 0 0-.094.03H4.25C2.037.548.217 2.368.217 4.58v48.405c0 2.212 1.82 4.03 4.03 4.03H39.03c2.21 0 4.03-1.818 4.03-4.03V15.61a1 1 0 0 0-.03-.28 1 1 0 0 0 0-.093 1 1 0 0 0-.03-.032 1 1 0 0 0 0-.03 1 1 0 0 0-.032-.063 1 1 0 0 0-.03-.063 1 1 0 0 0-.032 0 1 1 0 0 0-.03-.063 1 1 0 0 0-.032-.03 1 1 0 0 0-.03-.063 1 1 0 0 0-.063-.062l-14.593-14a1 1 0 0 0-.062-.062A1 1 0 0 0 28 .708a1 1 0 0 0-.374-.157 1 1 0 0 0-.156 0 1 1 0 0 0-.03-.03l-.003-.003zM4.25 2.547h22.218v9.97c0 2.21 1.82 4.03 4.03 4.03h10.564v36.438a2.02 2.02 0 0 1-2.032 2.032H4.25c-1.13 0-2.032-.9-2.032-2.032V4.58c0-1.13.902-2.032 2.03-2.032zm24.218 1.345l10.375 9.937.75.718H30.5c-1.13 0-2.032-.9-2.032-2.03V3.89z" })
            );
        }

        function iconText() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "62", height: "62", viewBox: "0 0 62 62", xmlns: "http://www.w3.org/2000/svg" },
                h("path", { d: "M4.309 4.309h24.912v53.382h-6.525v3.559h16.608v-3.559h-6.525V4.309h24.912v10.676h3.559V.75H.75v14.235h3.559z", "fill-rule": "nonzero", fill: "#000" })
            );
        }

        function uploadIcon() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "37", height: "33", viewBox: "0 0 37 33" },
                h("path", { d: "M29.107 24.5c4.07 0 7.393-3.355 7.393-7.442 0-3.994-3.105-7.307-7.012-7.502l.468.415C29.02 4.52 24.34.5 18.886.5c-4.348 0-8.27 2.522-10.138 6.506l.446-.288C4.394 6.782.5 10.758.5 15.608c0 4.924 3.906 8.892 8.76 8.892h4.872c.635 0 1.095-.467 1.095-1.104 0-.636-.46-1.103-1.095-1.103H9.26c-3.644 0-6.63-3.035-6.63-6.744 0-3.71 2.926-6.685 6.57-6.685h.964l.14-.28.177-.362c1.477-3.4 4.744-5.576 8.347-5.576 4.58 0 8.45 3.452 9.01 8.072l.06.536.05.446h1.101c2.87 0 5.204 2.37 5.204 5.295s-2.333 5.296-5.204 5.296h-6.062c-.634 0-1.094.467-1.094 1.103 0 .637.46 1.104 1.094 1.104h6.12z" }),
                h("path", { d: "M23.196 18.92l-4.828-5.258-.366-.4-.368.398-4.828 5.196a1.13 1.13 0 0 0 0 1.546c.428.46 1.11.46 1.537 0l3.45-3.71-.868-.34v15.03c0 .64.445 1.118 1.075 1.118.63 0 1.075-.48 1.075-1.12V16.35l-.867.34 3.45 3.712a1 1 0 0 0 .767.345 1 1 0 0 0 .77-.345c.416-.33.416-1.036 0-1.485v.003z" })
            );
        }

        function dashboardBgIcon() {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "48", height: "69", viewBox: "0 0 48 69" },
                h("path", { d: "M.5 1.5h5zM10.5 1.5h5zM20.5 1.5h5zM30.504 1.5h5zM45.5 11.5v5zM45.5 21.5v5zM45.5 31.5v5zM45.5 41.502v5zM45.5 51.502v5zM45.5 61.5v5zM45.5 66.502h-4.998zM35.503 66.502h-5zM25.5 66.502h-5zM15.5 66.502h-5zM5.5 66.502h-5zM.5 66.502v-5zM.5 56.502v-5zM.5 46.503V41.5zM.5 36.5v-5zM.5 26.5v-5zM.5 16.5v-5zM.5 6.5V1.498zM44.807 11H36V2.195z" })
            );
        }

        module.exports = {
            defaultTabIcon: defaultTabIcon,
            iconCopy: iconCopy,
            iconResume: iconResume,
            iconPause: iconPause,
            iconRetry: iconRetry,
            iconEdit: iconEdit,
            localIcon: localIcon,
            closeIcon: closeIcon,
            pluginIcon: pluginIcon,
            checkIcon: checkIcon,
            iconAudio: iconAudio,
            iconVideo: iconVideo,
            iconPDF: iconPDF,
            iconFile: iconFile,
            iconText: iconText,
            uploadIcon: uploadIcon,
            dashboardBgIcon: dashboardBgIcon
        };

    },{"preact":46}],90:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../../core/Plugin');
        var Translator = require('../../core/Translator');
        var dragDrop = require('drag-drop');
        var DashboardUI = require('./Dashboard');
        var StatusBar = require('../StatusBar');
        var Informer = require('../Informer');
        var ThumbnailGenerator = require('../ThumbnailGenerator');

        var _require = require('../../core/Utils'),
            findAllDOMElements = _require.findAllDOMElements,
            toArray = _require.toArray;

        var prettyBytes = require('prettier-bytes');

        var _require2 = require('./icons'),
            defaultTabIcon = _require2.defaultTabIcon;

// Some code for managing focus was adopted from https://github.com/ghosh/micromodal
// MIT licence, https://github.com/ghosh/micromodal/blob/master/LICENSE.md
// Copyright (c) 2017 Indrashish Ghosh


        var FOCUSABLE_ELEMENTS = ['a[href]', 'area[href]', 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', 'select:not([disabled]):not([aria-hidden])', 'textarea:not([disabled]):not([aria-hidden])', 'button:not([disabled]):not([aria-hidden])', 'iframe', 'object', 'embed', '[contenteditable]', '[tabindex]:not([tabindex^="-"])'];

        /**
         * Dashboard UI with previews, metadata editing, tabs for various services and more
         */
        module.exports = function (_Plugin) {
            _inherits(Dashboard, _Plugin);

            function Dashboard(uppy, opts) {
                _classCallCheck(this, Dashboard);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.id = _this.opts.id || 'Dashboard';
                _this.title = 'Dashboard';
                _this.type = 'orchestrator';

                var defaultLocale = {
                    strings: {
                        selectToUpload: 'Select files to upload',
                        closeModal: 'Close Modal',
                        upload: 'Upload',
                        importFrom: 'Import files from',
                        dashboardWindowTitle: 'Uppy Dashboard Window (Press escape to close)',
                        dashboardTitle: 'Uppy Dashboard',
                        copyLinkToClipboardSuccess: 'Link copied to clipboard.',
                        copyLinkToClipboardFallback: 'Copy the URL below',
                        copyLink: 'Copy link',
                        fileSource: 'File source',
                        done: 'Done',
                        name: 'Name',
                        removeFile: 'Remove file',
                        editFile: 'Edit file',
                        editing: 'Editing',
                        finishEditingFile: 'Finish editing file',
                        localDisk: 'Local Disk',
                        myDevice: 'My Device',
                        dropPasteImport: 'Drop files here, paste, import from one of the locations above or',
                        dropPaste: 'Drop files here, paste or',
                        browse: 'browse',
                        fileProgress: 'File progress: upload speed and ETA',
                        numberOfSelectedFiles: 'Number of selected files',
                        uploadAllNewFiles: 'Upload all new files',
                        emptyFolderAdded: 'No files were added from empty folder',
                        uploadXFiles: {
                            0: 'Upload %{smart_count} file',
                            1: 'Upload %{smart_count} files'
                        },
                        uploadXNewFiles: {
                            0: 'Upload +%{smart_count} file',
                            1: 'Upload +%{smart_count} files'
                        },
                        folderAdded: {
                            0: 'Added %{smart_count} file from %{folder}',
                            1: 'Added %{smart_count} files from %{folder}'
                        }
                    }

                    // set default options
                };var defaultOptions = {
                    target: 'body',
                    metaFields: [],
                    trigger: '#uppy-select-files',
                    inline: false,
                    width: 750,
                    height: 550,
                    thumbnailWidth: 280,
                    defaultTabIcon: defaultTabIcon,
                    showProgressDetails: false,
                    hideUploadButton: false,
                    hideProgressAfterFinish: false,
                    note: null,
                    closeModalOnClickOutside: false,
                    disableStatusBar: false,
                    disableInformer: false,
                    disableThumbnailGenerator: false,
                    disablePageScrollWhenModalOpen: true,
                    onRequestCloseModal: function onRequestCloseModal() {
                        return _this.closeModal();
                    },
                    locale: defaultLocale

                    // merge default options with the ones set by user
                };_this.opts = _extends({}, defaultOptions, opts);

                _this.locale = _extends({}, defaultLocale, _this.opts.locale);
                _this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);

                _this.translator = new Translator({ locale: _this.locale });
                _this.i18n = _this.translator.translate.bind(_this.translator);

                _this.openModal = _this.openModal.bind(_this);
                _this.closeModal = _this.closeModal.bind(_this);
                _this.requestCloseModal = _this.requestCloseModal.bind(_this);
                _this.isModalOpen = _this.isModalOpen.bind(_this);

                _this.addTarget = _this.addTarget.bind(_this);
                _this.hideAllPanels = _this.hideAllPanels.bind(_this);
                _this.showPanel = _this.showPanel.bind(_this);
                _this.getFocusableNodes = _this.getFocusableNodes.bind(_this);
                _this.setFocusToFirstNode = _this.setFocusToFirstNode.bind(_this);
                _this.maintainFocus = _this.maintainFocus.bind(_this);

                _this.initEvents = _this.initEvents.bind(_this);
                _this.onKeydown = _this.onKeydown.bind(_this);
                _this.handleClickOutside = _this.handleClickOutside.bind(_this);
                _this.handleFileCard = _this.handleFileCard.bind(_this);
                _this.handleDrop = _this.handleDrop.bind(_this);
                _this.handlePaste = _this.handlePaste.bind(_this);
                _this.handleInputChange = _this.handleInputChange.bind(_this);
                _this.updateDashboardElWidth = _this.updateDashboardElWidth.bind(_this);
                _this.render = _this.render.bind(_this);
                _this.install = _this.install.bind(_this);
                return _this;
            }

            Dashboard.prototype.addTarget = function addTarget(plugin) {
                var callerPluginId = plugin.id || plugin.constructor.name;
                var callerPluginName = plugin.title || callerPluginId;
                var callerPluginType = plugin.type;

                if (callerPluginType !== 'acquirer' && callerPluginType !== 'progressindicator' && callerPluginType !== 'presenter') {
                    var msg = 'Dashboard: Modal can only be used by plugins of types: acquirer, progressindicator, presenter';
                    this.uppy.log(msg);
                    return;
                }

                var target = {
                    id: callerPluginId,
                    name: callerPluginName,
                    type: callerPluginType
                };

                var state = this.getPluginState();
                var newTargets = state.targets.slice();
                newTargets.push(target);

                this.setPluginState({
                    targets: newTargets
                });

                return this.el;
            };

            Dashboard.prototype.hideAllPanels = function hideAllPanels() {
                this.setPluginState({
                    activePanel: false
                });
            };

            Dashboard.prototype.showPanel = function showPanel(id) {
                var _getPluginState = this.getPluginState(),
                    targets = _getPluginState.targets;

                var activePanel = targets.filter(function (target) {
                    return target.type === 'acquirer' && target.id === id;
                })[0];

                this.setPluginState({
                    activePanel: activePanel
                });
            };

            Dashboard.prototype.requestCloseModal = function requestCloseModal() {
                if (this.opts.onRequestCloseModal) {
                    return this.opts.onRequestCloseModal();
                } else {
                    this.closeModal();
                }
            };

            Dashboard.prototype.getFocusableNodes = function getFocusableNodes() {
                var nodes = this.el.querySelectorAll(FOCUSABLE_ELEMENTS);
                return Object.keys(nodes).map(function (key) {
                    return nodes[key];
                });
            };

            Dashboard.prototype.setFocusToFirstNode = function setFocusToFirstNode() {
                var focusableNodes = this.getFocusableNodes();
                if (focusableNodes.length) focusableNodes[0].focus();
            };

            Dashboard.prototype.maintainFocus = function maintainFocus(event) {
                var focusableNodes = this.getFocusableNodes();
                var focusedItemIndex = focusableNodes.indexOf(document.activeElement);

                if (event.shiftKey && focusedItemIndex === 0) {
                    focusableNodes[focusableNodes.length - 1].focus();
                    event.preventDefault();
                }

                if (!event.shiftKey && focusedItemIndex === focusableNodes.length - 1) {
                    focusableNodes[0].focus();
                    event.preventDefault();
                }
            };

            Dashboard.prototype.openModal = function openModal() {
                this.setPluginState({
                    isHidden: false
                });

                // save scroll position
                this.savedScrollPosition = window.scrollY;
                // save active element, so we can restore focus when modal is closed
                this.savedActiveElement = document.activeElement;

                if (this.opts.disablePageScrollWhenModalOpen) {
                    document.body.classList.add('uppy-Dashboard-isOpen');
                }

                this.updateDashboardElWidth();
                this.setFocusToFirstNode();
            };

            Dashboard.prototype.closeModal = function closeModal() {
                this.setPluginState({
                    isHidden: true
                });

                if (this.opts.disablePageScrollWhenModalOpen) {
                    document.body.classList.remove('uppy-Dashboard-isOpen');
                }

                this.savedActiveElement.focus();
            };

            Dashboard.prototype.isModalOpen = function isModalOpen() {
                return !this.getPluginState().isHidden || false;
            };

            Dashboard.prototype.onKeydown = function onKeydown(event) {
                // close modal on esc key press
                if (event.keyCode === 27) this.requestCloseModal(event);
                // maintainFocus on tab key press
                if (event.keyCode === 9) this.maintainFocus(event);
            };

            Dashboard.prototype.handleClickOutside = function handleClickOutside() {
                if (this.opts.closeModalOnClickOutside) this.requestCloseModal();
            };

            Dashboard.prototype.handlePaste = function handlePaste(ev) {
                var _this2 = this;

                var files = toArray(ev.clipboardData.items);
                files.forEach(function (file) {
                    if (file.kind !== 'file') return;

                    var blob = file.getAsFile();
                    if (!blob) {
                        _this2.uppy.log('[Dashboard] File pasted, but the file blob is empty');
                        _this2.uppy.info('Error pasting file', 'error');
                        return;
                    }
                    _this2.uppy.log('[Dashboard] File pasted');

                    _this2.uppy.addFile({
                        source: _this2.id,
                        name: file.name,
                        type: file.type,
                        data: blob
                    }).catch(function () {
                        // Ignore
                    });
                });
            };

            Dashboard.prototype.handleInputChange = function handleInputChange(ev) {
                var _this3 = this;

                ev.preventDefault();
                var files = toArray(ev.target.files);

                files.forEach(function (file) {
                    _this3.uppy.addFile({
                        source: _this3.id,
                        name: file.name,
                        type: file.type,
                        data: file
                    }).catch(function () {
                        // Ignore
                    });
                });
            };

            Dashboard.prototype.initEvents = function initEvents() {
                var _this4 = this;

                // Modal open button
                var showModalTrigger = findAllDOMElements(this.opts.trigger);
                if (!this.opts.inline && showModalTrigger) {
                    showModalTrigger.forEach(function (trigger) {
                        return trigger.addEventListener('click', _this4.openModal);
                    });
                }

                if (!this.opts.inline && !showModalTrigger) {
                    this.uppy.log('Dashboard modal trigger not found. Make sure `trigger` is set in Dashboard options unless you are planning to call openModal() method yourself');
                }

                if (!this.opts.inline) {
                    document.addEventListener('keydown', this.onKeydown);
                }

                // Drag Drop
                this.removeDragDropListener = dragDrop(this.el, function (files) {
                    _this4.handleDrop(files);
                });

                this.uppy.on('dashboard:file-card', this.handleFileCard);

                this.updateDashboardElWidth();
                window.addEventListener('resize', this.updateDashboardElWidth);
            };

            Dashboard.prototype.removeEvents = function removeEvents() {
                var _this5 = this;

                var showModalTrigger = findAllDOMElements(this.opts.trigger);
                if (!this.opts.inline && showModalTrigger) {
                    showModalTrigger.forEach(function (trigger) {
                        return trigger.removeEventListener('click', _this5.openModal);
                    });
                }

                if (!this.opts.inline) {
                    document.removeEventListener('keydown', this.onKeydown);
                }

                this.removeDragDropListener();
                this.uppy.off('dashboard:file-card', this.handleFileCard);
                window.removeEventListener('resize', this.updateDashboardElWidth);
            };

            Dashboard.prototype.updateDashboardElWidth = function updateDashboardElWidth() {
                var dashboardEl = this.el.querySelector('.uppy-Dashboard-inner');
                this.uppy.log('Dashboard width: ' + dashboardEl.offsetWidth);

                this.setPluginState({
                    containerWidth: dashboardEl.offsetWidth
                });
            };

            Dashboard.prototype.handleFileCard = function handleFileCard(fileId) {
                this.setPluginState({
                    fileCardFor: fileId || false
                });
            };

            Dashboard.prototype.handleDrop = function handleDrop(files) {
                var _this6 = this;

                this.uppy.log('[Dashboard] Files were dropped');

                files.forEach(function (file) {
                    _this6.uppy.addFile({
                        source: _this6.id,
                        name: file.name,
                        type: file.type,
                        data: file
                    }).catch(function () {
                        // Ignore
                    });
                });
            };

            Dashboard.prototype.render = function render(state) {
                var _this7 = this;

                var pluginState = this.getPluginState();
                var files = state.files;

                var newFiles = Object.keys(files).filter(function (file) {
                    return !files[file].progress.uploadStarted;
                });
                var inProgressFiles = Object.keys(files).filter(function (file) {
                    return !files[file].progress.uploadComplete && files[file].progress.uploadStarted && !files[file].isPaused;
                });

                var inProgressFilesArray = [];
                inProgressFiles.forEach(function (file) {
                    inProgressFilesArray.push(files[file]);
                });

                var totalSize = 0;
                var totalUploadedSize = 0;
                inProgressFilesArray.forEach(function (file) {
                    totalSize = totalSize + (file.progress.bytesTotal || 0);
                    totalUploadedSize = totalUploadedSize + (file.progress.bytesUploaded || 0);
                });
                totalSize = prettyBytes(totalSize);
                totalUploadedSize = prettyBytes(totalUploadedSize);

                var attachRenderFunctionToTarget = function attachRenderFunctionToTarget(target) {
                    var plugin = _this7.uppy.getPlugin(target.id);
                    return _extends({}, target, {
                        icon: plugin.icon || _this7.opts.defaultTabIcon,
                        render: plugin.render
                    });
                };

                var isSupported = function isSupported(target) {
                    var plugin = _this7.uppy.getPlugin(target.id);
                    // If the plugin does not provide a `supported` check, assume the plugin works everywhere.
                    if (typeof plugin.isSupported !== 'function') {
                        return true;
                    }
                    return plugin.isSupported();
                };

                var acquirers = pluginState.targets.filter(function (target) {
                    return target.type === 'acquirer' && isSupported(target);
                }).map(attachRenderFunctionToTarget);

                var progressindicators = pluginState.targets.filter(function (target) {
                    return target.type === 'progressindicator';
                }).map(attachRenderFunctionToTarget);

                var startUpload = function startUpload(ev) {
                    _this7.uppy.upload().catch(function (err) {
                        // Log error.
                        _this7.uppy.log(err.stack || err.message || err);
                    });
                };

                var cancelUpload = function cancelUpload(fileID) {
                    _this7.uppy.emit('upload-cancel', fileID);
                    _this7.uppy.removeFile(fileID);
                };

                var showFileCard = function showFileCard(fileID) {
                    _this7.uppy.emit('dashboard:file-card', fileID);
                };

                var fileCardDone = function fileCardDone(meta, fileID) {
                    _this7.uppy.setFileMeta(fileID, meta);
                    _this7.uppy.emit('dashboard:file-card');
                };

                return DashboardUI({
                    state: state,
                    modal: pluginState,
                    newFiles: newFiles,
                    files: files,
                    totalFileCount: Object.keys(files).length,
                    totalProgress: state.totalProgress,
                    acquirers: acquirers,
                    activePanel: pluginState.activePanel,
                    getPlugin: this.uppy.getPlugin,
                    progressindicators: progressindicators,
                    autoProceed: this.uppy.opts.autoProceed,
                    hideUploadButton: this.opts.hideUploadButton,
                    id: this.id,
                    closeModal: this.requestCloseModal,
                    handleClickOutside: this.handleClickOutside,
                    handleInputChange: this.handleInputChange,
                    handlePaste: this.handlePaste,
                    showProgressDetails: this.opts.showProgressDetails,
                    inline: this.opts.inline,
                    showPanel: this.showPanel,
                    hideAllPanels: this.hideAllPanels,
                    log: this.uppy.log,
                    i18n: this.i18n,
                    addFile: this.uppy.addFile,
                    removeFile: this.uppy.removeFile,
                    info: this.uppy.info,
                    note: this.opts.note,
                    metaFields: this.getPluginState().metaFields,
                    resumableUploads: this.uppy.state.capabilities.resumableUploads || false,
                    startUpload: startUpload,
                    pauseUpload: this.uppy.pauseResume,
                    retryUpload: this.uppy.retryUpload,
                    cancelUpload: cancelUpload,
                    fileCardFor: pluginState.fileCardFor,
                    showFileCard: showFileCard,
                    fileCardDone: fileCardDone,
                    updateDashboardElWidth: this.updateDashboardElWidth,
                    maxWidth: this.opts.maxWidth,
                    maxHeight: this.opts.maxHeight,
                    currentWidth: pluginState.containerWidth,
                    isWide: pluginState.containerWidth > 400
                });
            };

            Dashboard.prototype.discoverProviderPlugins = function discoverProviderPlugins() {
                var _this8 = this;

                this.uppy.iteratePlugins(function (plugin) {
                    if (plugin && !plugin.target && plugin.opts && plugin.opts.target === _this8.constructor) {
                        _this8.addTarget(plugin);
                    }
                });
            };

            Dashboard.prototype.install = function install() {
                var _this9 = this;

                // Set default state for Modal
                this.setPluginState({
                    isHidden: true,
                    showFileCard: false,
                    activePanel: false,
                    metaFields: this.opts.metaFields,
                    targets: []
                });

                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }

                var plugins = this.opts.plugins || [];
                plugins.forEach(function (pluginID) {
                    var plugin = _this9.uppy.getPlugin(pluginID);
                    if (plugin) plugin.mount(_this9, plugin);
                });

                if (!this.opts.disableStatusBar) {
                    this.uppy.use(StatusBar, {
                        target: this,
                        hideUploadButton: this.opts.hideUploadButton,
                        hideAfterFinish: this.opts.hideProgressAfterFinish,
                        locale: this.opts.locale
                    });
                }

                if (!this.opts.disableInformer) {
                    this.uppy.use(Informer, {
                        target: this
                    });
                }

                if (!this.opts.disableThumbnailGenerator) {
                    this.uppy.use(ThumbnailGenerator, {
                        thumbnailWidth: this.opts.thumbnailWidth
                    });
                }

                this.discoverProviderPlugins();

                this.initEvents();
            };

            Dashboard.prototype.uninstall = function uninstall() {
                var _this10 = this;

                if (!this.opts.disableInformer) {
                    var informer = this.uppy.getPlugin('Informer');
                    // Checking if this plugin exists, in case it was removed by uppy-core
                    // before the Dashboard was.
                    if (informer) this.uppy.removePlugin(informer);
                }

                if (!this.opts.disableStatusBar) {
                    var statusBar = this.uppy.getPlugin('StatusBar');
                    if (statusBar) this.uppy.removePlugin(statusBar);
                }

                if (!this.opts.disableThumbnailGenerator) {
                    var thumbnail = this.uppy.getPlugin('ThumbnailGenerator');
                    if (thumbnail) this.uppy.removePlugin(thumbnail);
                }

                var plugins = this.opts.plugins || [];
                plugins.forEach(function (pluginID) {
                    var plugin = _this10.uppy.getPlugin(pluginID);
                    if (plugin) plugin.unmount();
                });

                this.unmount();
                this.removeEvents();
            };

            return Dashboard;
        }(Plugin);

    },{"../../core/Plugin":74,"../../core/Translator":75,"../../core/Utils":77,"../Informer":101,"../StatusBar":117,"../ThumbnailGenerator":118,"./Dashboard":82,"./icons":89,"drag-drop":16,"prettier-bytes":47}],91:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../../core/Plugin');
        var Translator = require('../../core/Translator');

        var _require = require('../../core/Utils'),
            toArray = _require.toArray;

        var dragDrop = require('drag-drop');

        var _require2 = require('preact'),
            h = _require2.h;

        /**
         * Drag & Drop plugin
         *
         */


        module.exports = function (_Plugin) {
            _inherits(DragDrop, _Plugin);

            function DragDrop(uppy, opts) {
                _classCallCheck(this, DragDrop);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'acquirer';
                _this.id = _this.opts.id || 'DragDrop';
                _this.title = 'Drag & Drop';

                var defaultLocale = {
                    strings: {
                        dropHereOr: 'Drop files here or',
                        browse: 'browse'
                    }

                    // Default options
                };var defaultOpts = {
                    target: null,
                    width: '100%',
                    height: '100%',
                    note: '',
                    locale: defaultLocale

                    // Merge default options with the ones set by user
                };_this.opts = _extends({}, defaultOpts, opts);

                // Check for browser dragDrop support
                _this.isDragDropSupported = _this.checkDragDropSupport();

                _this.locale = _extends({}, defaultLocale, _this.opts.locale);
                _this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);

                // i18n
                _this.translator = new Translator({ locale: _this.locale });
                _this.i18n = _this.translator.translate.bind(_this.translator);

                // Bind `this` to class methods
                _this.handleDrop = _this.handleDrop.bind(_this);
                _this.handleBrowseClick = _this.handleBrowseClick.bind(_this);
                _this.handleInputChange = _this.handleInputChange.bind(_this);
                _this.checkDragDropSupport = _this.checkDragDropSupport.bind(_this);
                _this.render = _this.render.bind(_this);
                return _this;
            }

            /**
             * Checks if the browser supports Drag & Drop (not supported on mobile devices, for example).
             * @return {Boolean}
             */


            DragDrop.prototype.checkDragDropSupport = function checkDragDropSupport() {
                var div = document.createElement('div');

                if (!('draggable' in div) || !('ondragstart' in div && 'ondrop' in div)) {
                    return false;
                }

                if (!('FormData' in window)) {
                    return false;
                }

                if (!('FileReader' in window)) {
                    return false;
                }

                return true;
            };

            DragDrop.prototype.handleDrop = function handleDrop(files) {
                var _this2 = this;

                this.uppy.log('[DragDrop] Files dropped');

                files.forEach(function (file) {
                    _this2.uppy.addFile({
                        source: _this2.id,
                        name: file.name,
                        type: file.type,
                        data: file
                    }).catch(function () {
                        // Ignore
                    });
                });
            };

            DragDrop.prototype.handleInputChange = function handleInputChange(ev) {
                var _this3 = this;

                this.uppy.log('[DragDrop] Files selected through input');

                var files = toArray(ev.target.files);

                files.forEach(function (file) {
                    _this3.uppy.addFile({
                        source: _this3.id,
                        name: file.name,
                        type: file.type,
                        data: file
                    }).catch(function () {
                        // Ignore
                    });
                });
            };

            DragDrop.prototype.handleBrowseClick = function handleBrowseClick(ev) {
                ev.stopPropagation();
                this.input.click();
            };

            DragDrop.prototype.render = function render(state) {
                var _this4 = this;

                var DragDropClass = 'uppy uppy-DragDrop-container ' + (this.isDragDropSupported ? 'is-dragdrop-supported' : '');
                var DragDropStyle = {
                    width: this.opts.width,
                    height: this.opts.height
                };
                return h(
                    'div',
                    { 'class': DragDropClass, style: DragDropStyle },
                    h(
                        'div',
                        { 'class': 'uppy-DragDrop-inner' },
                        h(
                            'svg',
                            { 'aria-hidden': 'true', 'class': 'UppyIcon uppy-DragDrop-arrow', width: '16', height: '16', viewBox: '0 0 16 16', xmlns: 'http://www.w3.org/2000/svg' },
                            h('path', { d: 'M11 10V0H5v10H2l6 6 6-6h-3zm0 0', 'fill-rule': 'evenodd' })
                        ),
                        h('input', { 'class': 'uppy-DragDrop-input',
                            type: 'file',
                            name: 'files[]',
                            multiple: 'true',
                            ref: function ref(input) {
                                _this4.input = input;
                            },
                            onchange: this.handleInputChange }),
                        h(
                            'label',
                            { 'class': 'uppy-DragDrop-label', onclick: this.handleBrowseClick },
                            this.i18n('dropHereOr'),
                            ' ',
                            h(
                                'span',
                                { 'class': 'uppy-DragDrop-dragText' },
                                this.i18n('browse')
                            )
                        ),
                        h(
                            'span',
                            { 'class': 'uppy-DragDrop-note' },
                            this.opts.note
                        )
                    )
                );
            };

            DragDrop.prototype.install = function install() {
                var _this5 = this;

                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }
                this.removeDragDropListener = dragDrop(this.el, function (files) {
                    _this5.handleDrop(files);
                    _this5.uppy.log(files);
                });
            };

            DragDrop.prototype.uninstall = function uninstall() {
                this.unmount();
                this.removeDragDropListener();
            };

            return DragDrop;
        }(Plugin);

    },{"../../core/Plugin":74,"../../core/Translator":75,"../../core/Utils":77,"drag-drop":16,"preact":46}],92:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

        module.exports = {
            folder: function folder() {
                return h(
                    "svg",
                    { "aria-hidden": "true", "class": "UppyIcon", style: "width:16px;margin-right:3px", viewBox: "0 0 276.157 276.157" },
                    h("path", { d: "M273.08 101.378c-3.3-4.65-8.86-7.32-15.254-7.32h-24.34V67.59c0-10.2-8.3-18.5-18.5-18.5h-85.322c-3.63 0-9.295-2.875-11.436-5.805l-6.386-8.735c-4.982-6.814-15.104-11.954-23.546-11.954H58.73c-9.292 0-18.638 6.608-21.737 15.372l-2.033 5.752c-.958 2.71-4.72 5.37-7.596 5.37H18.5C8.3 49.09 0 57.39 0 67.59v167.07c0 .886.16 1.73.443 2.52.152 3.306 1.18 6.424 3.053 9.064 3.3 4.652 8.86 7.32 15.255 7.32h188.487c11.395 0 23.27-8.425 27.035-19.18l40.677-116.188c2.11-6.035 1.43-12.164-1.87-16.816zM18.5 64.088h8.864c9.295 0 18.64-6.607 21.738-15.37l2.032-5.75c.96-2.712 4.722-5.373 7.597-5.373h29.565c3.63 0 9.295 2.876 11.437 5.806l6.386 8.735c4.982 6.815 15.104 11.954 23.546 11.954h85.322c1.898 0 3.5 1.602 3.5 3.5v26.47H69.34c-11.395 0-23.27 8.423-27.035 19.178L15 191.23V67.59c0-1.898 1.603-3.5 3.5-3.5zm242.29 49.15l-40.676 116.188c-1.674 4.78-7.812 9.135-12.877 9.135H18.75c-1.447 0-2.576-.372-3.02-.997-.442-.625-.422-1.814.057-3.18l40.677-116.19c1.674-4.78 7.812-9.134 12.877-9.134h188.487c1.448 0 2.577.372 3.02.997.443.625.423 1.814-.056 3.18z" })
                );
            },
            file: function file() {
                return h(
                    "svg",
                    { "aria-hidden": "true", "class": "UppyIcon", width: "11", height: "14.5", viewBox: "0 0 44 58" },
                    h("path", { d: "M27.437.517a1 1 0 0 0-.094.03H4.25C2.037.548.217 2.368.217 4.58v48.405c0 2.212 1.82 4.03 4.03 4.03H39.03c2.21 0 4.03-1.818 4.03-4.03V15.61a1 1 0 0 0-.03-.28 1 1 0 0 0 0-.093 1 1 0 0 0-.03-.032 1 1 0 0 0 0-.03 1 1 0 0 0-.032-.063 1 1 0 0 0-.03-.063 1 1 0 0 0-.032 0 1 1 0 0 0-.03-.063 1 1 0 0 0-.032-.03 1 1 0 0 0-.03-.063 1 1 0 0 0-.063-.062l-14.593-14a1 1 0 0 0-.062-.062A1 1 0 0 0 28 .708a1 1 0 0 0-.374-.157 1 1 0 0 0-.156 0 1 1 0 0 0-.03-.03l-.003-.003zM4.25 2.547h22.218v9.97c0 2.21 1.82 4.03 4.03 4.03h10.564v36.438a2.02 2.02 0 0 1-2.032 2.032H4.25c-1.13 0-2.032-.9-2.032-2.032V4.58c0-1.13.902-2.032 2.03-2.032zm24.218 1.345l10.375 9.937.75.718H30.5c-1.13 0-2.032-.9-2.032-2.03V3.89z" })
                );
            }
        };

    },{"preact":46}],93:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../../core/Plugin');
        var Provider = require('../Provider');
        var View = require('../Provider/view');
        var icons = require('./icons');

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (_Plugin) {
            _inherits(Dropbox, _Plugin);

            function Dropbox(uppy, opts) {
                _classCallCheck(this, Dropbox);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'acquirer';
                _this.id = _this.opts.id || 'Dropbox';
                _this.title = 'Dropbox';
                _this.icon = function () {
                    return h(
                        'svg',
                        { 'class': 'UppyIcon', width: '128', height: '118', viewBox: '0 0 128 118' },
                        h('path', { d: 'M38.145.777L1.108 24.96l25.608 20.507 37.344-23.06z' }),
                        h('path', { d: 'M1.108 65.975l37.037 24.183L64.06 68.525l-37.343-23.06zM64.06 68.525l25.917 21.633 37.036-24.183-25.61-20.51z' }),
                        h('path', { d: 'M127.014 24.96L89.977.776 64.06 22.407l37.345 23.06zM64.136 73.18l-25.99 21.567-11.122-7.262v8.142l37.112 22.256 37.114-22.256v-8.142l-11.12 7.262z' })
                    );
                };

                // writing out the key explicitly for readability the key used to store
                // the provider instance must be equal to this.id.
                _this[_this.id] = new Provider(uppy, {
                    host: _this.opts.host,
                    provider: 'dropbox'
                });

                _this.files = [];

                _this.onAuth = _this.onAuth.bind(_this);
                _this.render = _this.render.bind(_this);

                // set default options
                var defaultOptions = {};

                // merge default options with the ones set by user
                _this.opts = _extends({}, defaultOptions, opts);
                return _this;
            }

            Dropbox.prototype.install = function install() {
                this.view = new View(this);
                // Set default state for Dropbox
                this.setPluginState({
                    authenticated: false,
                    files: [],
                    folders: [],
                    directories: [],
                    activeRow: -1,
                    filterInput: '',
                    isSearchVisible: false
                });

                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }
            };

            Dropbox.prototype.uninstall = function uninstall() {
                this.view.tearDown();
                this.unmount();
            };

            Dropbox.prototype.onAuth = function onAuth(authenticated) {
                this.setPluginState({ authenticated: authenticated });
                if (authenticated) {
                    this.view.getFolder();
                }
            };

            Dropbox.prototype.isFolder = function isFolder(item) {
                return item['.tag'] === 'folder';
            };

            Dropbox.prototype.getItemData = function getItemData(item) {
                return item;
            };

            Dropbox.prototype.getItemIcon = function getItemIcon(item) {
                return icons[item['.tag']]();
            };

            Dropbox.prototype.getItemSubList = function getItemSubList(item) {
                return item.entries;
            };

            Dropbox.prototype.getItemName = function getItemName(item) {
                return item.name || '';
            };

            Dropbox.prototype.getMimeType = function getMimeType(item) {
                // mime types aren't supported.
                return null;
            };

            Dropbox.prototype.getItemId = function getItemId(item) {
                return item.id;
            };

            Dropbox.prototype.getItemRequestPath = function getItemRequestPath(item) {
                return encodeURIComponent(item.path_lower);
            };

            Dropbox.prototype.getItemModifiedDate = function getItemModifiedDate(item) {
                return item.server_modified;
            };

            Dropbox.prototype.getItemThumbnailUrl = function getItemThumbnailUrl(item) {
                return this.opts.host + '/' + this.Dropbox.id + '/thumbnail/' + this.getItemRequestPath(item);
            };

            Dropbox.prototype.render = function render(state) {
                return this.view.render(state);
            };

            return Dropbox;
        }(Plugin);

    },{"../../core/Plugin":74,"../Provider":104,"../Provider/view":113,"./icons":92,"preact":46}],94:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../core/Plugin');

        var _require = require('preact'),
            h = _require.h;

        /**
         * Dummy
         * A test plugin, does nothing useful
         */


        module.exports = function (_Plugin) {
            _inherits(Dummy, _Plugin);

            function Dummy(uppy, opts) {
                _classCallCheck(this, Dummy);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'acquirer';
                _this.id = _this.opts.id || 'Dummy';
                _this.title = 'Mr. Plugin';

                // set default options
                var defaultOptions = {};

                // merge default options with the ones set by user
                _this.opts = _extends({}, defaultOptions, opts);

                _this.strange = h(
                    'h1',
                    null,
                    'this is strange 1'
                );
                _this.render = _this.render.bind(_this);
                _this.install = _this.install.bind(_this);
                return _this;
            }

            Dummy.prototype.addFakeFileJustToTest = function addFakeFileJustToTest() {
                var blob = new Blob(['data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTIwIDEyMCI+CiAgPGNpcmNsZSBjeD0iNjAiIGN5PSI2MCIgcj0iNTAiLz4KPC9zdmc+Cg=='], { type: 'image/svg+xml' });
                var file = {
                    source: 'acceptance-test',
                    name: 'test-file',
                    type: 'image/svg+xml',
                    data: blob
                };
                this.props.log('Adding fake file blob');
                this.props.addFile(file).catch(function () {
                    // Ignore
                });
            };

            Dummy.prototype.render = function render(state) {
                var bla = h(
                    'h2',
                    null,
                    'this is strange 2'
                );
                return h(
                    'div',
                    { 'class': 'wow-this-works' },
                    h('input', { 'class': 'UppyDummy-firstInput', type: 'text', value: 'hello' }),
                    this.strange,
                    bla,
                    state.dummy.text
                );
            };

            Dummy.prototype.install = function install() {
                var _this2 = this;

                this.uppy.setState({
                    dummy: { text: '123' }
                });

                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }

                setTimeout(function () {
                    _this2.uppy.setState({
                        dummy: { text: '!!!' }
                    });
                }, 2000);
            };

            return Dummy;
        }(Plugin);

// module.exports = function (core, opts) {
//   if (!(this instanceof Dummy)) {
//     return new Dummy(core, opts)
//   }
// }

    },{"../core/Plugin":74,"preact":46}],95:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../core/Plugin');

        var _require = require('../core/Utils'),
            toArray = _require.toArray;

        var Translator = require('../core/Translator');

        var _require2 = require('preact'),
            h = _require2.h;

        module.exports = function (_Plugin) {
            _inherits(FileInput, _Plugin);

            function FileInput(uppy, opts) {
                _classCallCheck(this, FileInput);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.id = _this.opts.id || 'FileInput';
                _this.title = 'File Input';
                _this.type = 'acquirer';

                var defaultLocale = {
                    strings: {
                        chooseFiles: 'Choose files'
                    }

                    // Default options
                };var defaultOptions = {
                    target: null,
                    allowMultipleFiles: true,
                    pretty: true,
                    inputName: 'files[]',
                    locale: defaultLocale

                    // Merge default options with the ones set by user
                };_this.opts = _extends({}, defaultOptions, opts);

                _this.locale = _extends({}, defaultLocale, _this.opts.locale);
                _this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);

                // i18n
                _this.translator = new Translator({ locale: _this.locale });
                _this.i18n = _this.translator.translate.bind(_this.translator);

                _this.render = _this.render.bind(_this);
                _this.handleInputChange = _this.handleInputChange.bind(_this);
                _this.handleClick = _this.handleClick.bind(_this);
                return _this;
            }

            FileInput.prototype.handleInputChange = function handleInputChange(ev) {
                var _this2 = this;

                this.uppy.log('[FileInput] Something selected through input...');

                var files = toArray(ev.target.files);

                files.forEach(function (file) {
                    _this2.uppy.addFile({
                        source: _this2.id,
                        name: file.name,
                        type: file.type,
                        data: file
                    }).catch(function () {
                        // Ignore
                    });
                });
            };

            FileInput.prototype.handleClick = function handleClick(ev) {
                this.input.click();
            };

            FileInput.prototype.render = function render(state) {
                var _this3 = this;

                var hiddenInputStyle = {
                    width: '0.1px',
                    height: '0.1px',
                    opacity: 0,
                    overflow: 'hidden',
                    position: 'absolute',
                    zIndex: -1
                };

                return h(
                    'div',
                    { 'class': 'uppy uppy-FileInput-container' },
                    h('input', { 'class': 'uppy-FileInput-input',
                        style: this.opts.pretty && hiddenInputStyle,
                        type: 'file',
                        name: this.opts.inputName,
                        onchange: this.handleInputChange,
                        multiple: this.opts.allowMultipleFiles,
                        ref: function ref(input) {
                            _this3.input = input;
                        } }),
                    this.opts.pretty && h(
                    'button',
                    { 'class': 'uppy-FileInput-btn', type: 'button', onclick: this.handleClick },
                    this.i18n('chooseFiles')
                    )
                );
            };

            FileInput.prototype.install = function install() {
                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }
            };

            FileInput.prototype.uninstall = function uninstall() {
                this.unmount();
            };

            return FileInput;
        }(Plugin);

    },{"../core/Plugin":74,"../core/Translator":75,"../core/Utils":77,"preact":46}],96:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var prettyBytes = require('prettier-bytes');
        var indexedDB = typeof window !== 'undefined' && (window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB);

        var isSupported = !!indexedDB;

        var DB_NAME = 'uppy-blobs';
        var STORE_NAME = 'files'; // maybe have a thumbnail store in the future
        var DEFAULT_EXPIRY = 24 * 60 * 60 * 1000; // 24 hours
        var DB_VERSION = 3;

// Set default `expires` dates on existing stored blobs.
        function migrateExpiration(store) {
            var request = store.openCursor();
            request.onsuccess = function (event) {
                var cursor = event.target.result;
                if (!cursor) {
                    return;
                }
                var entry = cursor.value;
                entry.expires = Date.now() + DEFAULT_EXPIRY;
                cursor.update(entry);
            };
        }

        function connect(dbName) {
            var request = indexedDB.open(dbName, DB_VERSION);
            return new _Promise(function (resolve, reject) {
                request.onupgradeneeded = function (event) {
                    var db = event.target.result;
                    var transaction = event.currentTarget.transaction;

                    if (event.oldVersion < 2) {
                        // Added in v2: DB structure changed to a single shared object store
                        var store = db.createObjectStore(STORE_NAME, { keyPath: 'id' });
                        store.createIndex('store', 'store', { unique: false });
                    }

                    if (event.oldVersion < 3) {
                        // Added in v3
                        var _store = transaction.objectStore(STORE_NAME);
                        _store.createIndex('expires', 'expires', { unique: false });

                        migrateExpiration(_store);
                    }

                    transaction.oncomplete = function () {
                        resolve(db);
                    };
                };
                request.onsuccess = function (event) {
                    resolve(event.target.result);
                };
                request.onerror = reject;
            });
        }

        function waitForRequest(request) {
            return new _Promise(function (resolve, reject) {
                request.onsuccess = function (event) {
                    resolve(event.target.result);
                };
                request.onerror = reject;
            });
        }

        var cleanedUp = false;

        var IndexedDBStore = function () {
            function IndexedDBStore(opts) {
                var _this = this;

                _classCallCheck(this, IndexedDBStore);

                this.opts = _extends({
                    dbName: DB_NAME,
                    storeName: 'default',
                    expires: DEFAULT_EXPIRY, // 24 hours
                    maxFileSize: 10 * 1024 * 1024, // 10 MB
                    maxTotalSize: 300 * 1024 * 1024 // 300 MB
                }, opts);

                this.name = this.opts.storeName;

                var createConnection = function createConnection() {
                    return connect(_this.opts.dbName);
                };

                if (!cleanedUp) {
                    cleanedUp = true;
                    this.ready = IndexedDBStore.cleanup().then(createConnection, createConnection);
                } else {
                    this.ready = createConnection();
                }
            }

            IndexedDBStore.prototype.key = function key(fileID) {
                return this.name + '!' + fileID;
            };

            /**
             * List all file blobs currently in the store.
             */


            IndexedDBStore.prototype.list = function list() {
                var _this2 = this;

                return this.ready.then(function (db) {
                    var transaction = db.transaction([STORE_NAME], 'readonly');
                    var store = transaction.objectStore(STORE_NAME);
                    var request = store.index('store').getAll(IDBKeyRange.only(_this2.name));
                    return waitForRequest(request);
                }).then(function (files) {
                    var result = {};
                    files.forEach(function (file) {
                        result[file.fileID] = file.data;
                    });
                    return result;
                });
            };

            /**
             * Get one file blob from the store.
             */


            IndexedDBStore.prototype.get = function get(fileID) {
                var _this3 = this;

                return this.ready.then(function (db) {
                    var transaction = db.transaction([STORE_NAME], 'readonly');
                    var request = transaction.objectStore(STORE_NAME).get(_this3.key(fileID));
                    return waitForRequest(request);
                }).then(function (result) {
                    return {
                        id: result.data.fileID,
                        data: result.data.data
                    };
                });
            };

            /**
             * Get the total size of all stored files.
             *
             * @private
             */


            IndexedDBStore.prototype.getSize = function getSize() {
                var _this4 = this;

                return this.ready.then(function (db) {
                    var transaction = db.transaction([STORE_NAME], 'readonly');
                    var store = transaction.objectStore(STORE_NAME);
                    var request = store.index('store').openCursor(IDBKeyRange.only(_this4.name));
                    return new _Promise(function (resolve, reject) {
                        var size = 0;
                        request.onsuccess = function (event) {
                            var cursor = event.target.result;
                            if (cursor) {
                                size += cursor.value.data.size;
                                cursor.continue();
                            } else {
                                resolve(size);
                            }
                        };
                        request.onerror = function () {
                            reject(new Error('Could not retrieve stored blobs size'));
                        };
                    });
                });
            };

            /**
             * Save a file in the store.
             */


            IndexedDBStore.prototype.put = function put(file) {
                var _this5 = this;

                if (file.data.size > this.opts.maxFileSize) {
                    return _Promise.reject(new Error('File is too big to store.'));
                }
                return this.getSize().then(function (size) {
                    if (size > _this5.opts.maxTotalSize) {
                        return _Promise.reject(new Error('No space left'));
                    }
                    return _this5.ready;
                }).then(function (db) {
                    var transaction = db.transaction([STORE_NAME], 'readwrite');
                    var request = transaction.objectStore(STORE_NAME).add({
                        id: _this5.key(file.id),
                        fileID: file.id,
                        store: _this5.name,
                        expires: Date.now() + _this5.opts.expires,
                        data: file.data
                    });
                    return waitForRequest(request);
                });
            };

            /**
             * Delete a file blob from the store.
             */


            IndexedDBStore.prototype.delete = function _delete(fileID) {
                var _this6 = this;

                return this.ready.then(function (db) {
                    var transaction = db.transaction([STORE_NAME], 'readwrite');
                    var request = transaction.objectStore(STORE_NAME).delete(_this6.key(fileID));
                    return waitForRequest(request);
                });
            };

            /**
             * Delete all stored blobs that have an expiry date that is before Date.now().
             * This is a static method because it deletes expired blobs from _all_ Uppy instances.
             */


            IndexedDBStore.cleanup = function cleanup() {
                return connect(DB_NAME).then(function (db) {
                    var transaction = db.transaction([STORE_NAME], 'readwrite');
                    var store = transaction.objectStore(STORE_NAME);
                    var request = store.index('expires').openCursor(IDBKeyRange.upperBound(Date.now()));
                    return new _Promise(function (resolve, reject) {
                        request.onsuccess = function (event) {
                            var cursor = event.target.result;
                            if (cursor) {
                                var entry = cursor.value;
                                console.log('[IndexedDBStore] Deleting record', entry.fileID, 'of size', prettyBytes(entry.data.size), '- expired on', new Date(entry.expires));
                                cursor.delete(); // Ignoring return value â€¦ it's not terrible if this goes wrong.
                                cursor.continue();
                            } else {
                                resolve(db);
                            }
                        };
                        request.onerror = reject;
                    });
                }).then(function (db) {
                    db.close();
                });
            };

            return IndexedDBStore;
        }();

        IndexedDBStore.isSupported = isSupported;

        module.exports = IndexedDBStore;

    },{"es6-promise":33,"prettier-bytes":47}],97:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        /**
         * Get uppy instance IDs for which state is stored.
         */
        function findUppyInstances() {
            var instances = [];
            for (var i = 0; i < localStorage.length; i++) {
                var key = localStorage.key(i);
                if (/^uppyState:/.test(key)) {
                    instances.push(key.slice('uppyState:'.length));
                }
            }
            return instances;
        }

        /**
         * Try to JSON-parse a string, return null on failure.
         */
        function maybeParse(str) {
            try {
                return JSON.parse(str);
            } catch (err) {
                return null;
            }
        }

        var cleanedUp = false;
        module.exports = function () {
            function MetaDataStore(opts) {
                _classCallCheck(this, MetaDataStore);

                this.opts = _extends({
                    expires: 24 * 60 * 60 * 1000 // 24 hours
                }, opts);
                this.name = 'uppyState:' + opts.storeName;

                if (!cleanedUp) {
                    cleanedUp = true;
                    MetaDataStore.cleanup();
                }
            }

            /**
             *
             */


            MetaDataStore.prototype.load = function load() {
                var savedState = localStorage.getItem(this.name);
                if (!savedState) return null;
                var data = maybeParse(savedState);
                if (!data) return null;

                // Upgrade pre-0.20.0 uppyState: it used to be just a flat object,
                // without `expires`.
                if (!data.metadata) {
                    this.save(data);
                    return data;
                }

                return data.metadata;
            };

            MetaDataStore.prototype.save = function save(metadata) {
                var expires = Date.now() + this.opts.expires;
                var state = JSON.stringify({
                    metadata: metadata,
                    expires: expires
                });
                localStorage.setItem(this.name, state);
            };

            /**
             * Remove all expired state.
             */


            MetaDataStore.cleanup = function cleanup() {
                var instanceIDs = findUppyInstances();
                var now = Date.now();
                instanceIDs.forEach(function (id) {
                    var data = localStorage.getItem('uppyState:' + id);
                    if (!data) return null;
                    var obj = maybeParse(data);
                    if (!obj) return null;

                    if (obj.expires && obj.expires < now) {
                        localStorage.removeItem('uppyState:' + id);
                    }
                });
            };

            return MetaDataStore;
        }();

    },{}],98:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var isSupported = typeof navigator !== 'undefined' && 'serviceWorker' in navigator;

        function waitForServiceWorker() {
            return new _Promise(function (resolve, reject) {
                if (!isSupported) {
                    reject(new Error('Unsupported'));
                } else if (navigator.serviceWorker.controller) {
                    // A serviceWorker is already registered and active.
                    resolve();
                } else {
                    navigator.serviceWorker.addEventListener('controllerchange', function () {
                        resolve();
                    });
                }
            });
        }

        var ServiceWorkerStore = function () {
            function ServiceWorkerStore(opts) {
                _classCallCheck(this, ServiceWorkerStore);

                this.ready = waitForServiceWorker();
                this.name = opts.storeName;
            }

            ServiceWorkerStore.prototype.list = function list() {
                var _this = this;

                var defer = {};
                var promise = new _Promise(function (resolve, reject) {
                    defer.resolve = resolve;
                    defer.reject = reject;
                });

                console.log('Loading stored blobs from Service Worker');
                var onMessage = function onMessage(event) {
                    if (event.data.store !== _this.name) {
                        return;
                    }
                    switch (event.data.type) {
                        case 'uppy/ALL_FILES':
                            defer.resolve(event.data.files);
                            navigator.serviceWorker.removeEventListener('message', onMessage);
                            break;
                    }
                };

                this.ready.then(function () {
                    navigator.serviceWorker.addEventListener('message', onMessage);

                    navigator.serviceWorker.controller.postMessage({
                        type: 'uppy/GET_FILES',
                        store: _this.name
                    });
                });

                return promise;
            };

            ServiceWorkerStore.prototype.put = function put(file) {
                var _this2 = this;

                return this.ready.then(function () {
                    navigator.serviceWorker.controller.postMessage({
                        type: 'uppy/ADD_FILE',
                        store: _this2.name,
                        file: file
                    });
                });
            };

            ServiceWorkerStore.prototype.delete = function _delete(fileID) {
                var _this3 = this;

                return this.ready.then(function () {
                    navigator.serviceWorker.controller.postMessage({
                        type: 'uppy/REMOVE_FILE',
                        store: _this3.name,
                        fileID: fileID
                    });
                });
            };

            return ServiceWorkerStore;
        }();

        ServiceWorkerStore.isSupported = isSupported;

        module.exports = ServiceWorkerStore;

    },{"es6-promise":33}],99:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var Plugin = require('../../core/Plugin');
        var ServiceWorkerStore = require('./ServiceWorkerStore');
        var IndexedDBStore = require('./IndexedDBStore');
        var MetaDataStore = require('./MetaDataStore');

        /**
         * The Golden Retriever plugin â€” restores selected files and resumes uploads
         * after a closed tab or a browser crash!
         *
         * Uses localStorage, IndexedDB and ServiceWorker to do its magic, read more:
         * https://uppy.io/blog/2017/07/golden-retriever/
         */
        module.exports = function (_Plugin) {
            _inherits(GoldenRetriever, _Plugin);

            function GoldenRetriever(uppy, opts) {
                _classCallCheck(this, GoldenRetriever);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'debugger';
                _this.id = 'GoldenRetriever';
                _this.title = 'Golden Retriever';

                var defaultOptions = {
                    expires: 24 * 60 * 60 * 1000, // 24 hours
                    serviceWorker: false
                };

                _this.opts = _extends({}, defaultOptions, opts);

                _this.MetaDataStore = new MetaDataStore({
                    expires: _this.opts.expires,
                    storeName: uppy.getID()
                });
                _this.ServiceWorkerStore = null;
                if (_this.opts.serviceWorker) {
                    _this.ServiceWorkerStore = new ServiceWorkerStore({ storeName: uppy.getID() });
                }
                _this.IndexedDBStore = new IndexedDBStore(_extends({ expires: _this.opts.expires }, opts.indexedDB || {}, { storeName: uppy.getID() }));

                _this.saveFilesStateToLocalStorage = _this.saveFilesStateToLocalStorage.bind(_this);
                _this.loadFilesStateFromLocalStorage = _this.loadFilesStateFromLocalStorage.bind(_this);
                _this.loadFileBlobsFromServiceWorker = _this.loadFileBlobsFromServiceWorker.bind(_this);
                _this.loadFileBlobsFromIndexedDB = _this.loadFileBlobsFromIndexedDB.bind(_this);
                _this.onBlobsLoaded = _this.onBlobsLoaded.bind(_this);
                return _this;
            }

            GoldenRetriever.prototype.loadFilesStateFromLocalStorage = function loadFilesStateFromLocalStorage() {
                var savedState = this.MetaDataStore.load();

                if (savedState) {
                    this.uppy.log('[GoldenRetriever] Recovered some state from Local Storage');
                    this.uppy.setState({
                        currentUploads: savedState.currentUploads || {},
                        files: savedState.files || {}
                    });

                    this.savedPluginData = savedState.pluginData;
                }
            };

            /**
             * Get file objects that are currently waiting: they've been selected,
             * but aren't yet being uploaded.
             */


            GoldenRetriever.prototype.getWaitingFiles = function getWaitingFiles() {
                var _this2 = this;

                var waitingFiles = {};

                var allFiles = this.uppy.state.files;
                Object.keys(allFiles).forEach(function (fileID) {
                    var file = _this2.uppy.getFile(fileID);
                    if (!file.progress || !file.progress.uploadStarted) {
                        waitingFiles[fileID] = file;
                    }
                });

                return waitingFiles;
            };

            /**
             * Get file objects that are currently being uploaded. If a file has finished
             * uploading, but the other files in the same batch have not, the finished
             * file is also returned.
             */


            GoldenRetriever.prototype.getUploadingFiles = function getUploadingFiles() {
                var _this3 = this;

                var uploadingFiles = {};

                var currentUploads = this.uppy.state.currentUploads;

                if (currentUploads) {
                    var uploadIDs = Object.keys(currentUploads);
                    uploadIDs.forEach(function (uploadID) {
                        var filesInUpload = currentUploads[uploadID].fileIDs;
                        filesInUpload.forEach(function (fileID) {
                            uploadingFiles[fileID] = _this3.uppy.getFile(fileID);
                        });
                    });
                }

                return uploadingFiles;
            };

            GoldenRetriever.prototype.saveFilesStateToLocalStorage = function saveFilesStateToLocalStorage() {
                var filesToSave = _extends(this.getWaitingFiles(), this.getUploadingFiles());

                var pluginData = {};
                // TODO Find a better way to do this?
                // Other plugins can attach a restore:get-data listener that receives this callback.
                // Plugins can then use this callback (sync) to provide data to be stored.
                this.uppy.emit('restore:get-data', function (data) {
                    _extends(pluginData, data);
                });

                this.MetaDataStore.save({
                    currentUploads: this.uppy.state.currentUploads,
                    files: filesToSave,
                    pluginData: pluginData
                });
            };

            GoldenRetriever.prototype.loadFileBlobsFromServiceWorker = function loadFileBlobsFromServiceWorker() {
                var _this4 = this;

                this.ServiceWorkerStore.list().then(function (blobs) {
                    var numberOfFilesRecovered = Object.keys(blobs).length;
                    var numberOfFilesTryingToRecover = Object.keys(_this4.uppy.state.files).length;
                    if (numberOfFilesRecovered === numberOfFilesTryingToRecover) {
                        _this4.uppy.log('[GoldenRetriever] Successfully recovered ' + numberOfFilesRecovered + ' blobs from Service Worker!');
                        _this4.uppy.info('Successfully recovered ' + numberOfFilesRecovered + ' files', 'success', 3000);
                        _this4.onBlobsLoaded(blobs);
                    } else {
                        _this4.uppy.log('[GoldenRetriever] Failed to recover blobs from Service Worker, trying IndexedDB now...');
                        _this4.loadFileBlobsFromIndexedDB();
                    }
                });
            };

            GoldenRetriever.prototype.loadFileBlobsFromIndexedDB = function loadFileBlobsFromIndexedDB() {
                var _this5 = this;

                this.IndexedDBStore.list().then(function (blobs) {
                    var numberOfFilesRecovered = Object.keys(blobs).length;

                    if (numberOfFilesRecovered > 0) {
                        _this5.uppy.log('[GoldenRetriever] Successfully recovered ' + numberOfFilesRecovered + ' blobs from Indexed DB!');
                        _this5.uppy.info('Successfully recovered ' + numberOfFilesRecovered + ' files', 'success', 3000);
                        return _this5.onBlobsLoaded(blobs);
                    }
                    _this5.uppy.log('[GoldenRetriever] Couldnâ€™t recover anything from IndexedDB :(');
                });
            };

            GoldenRetriever.prototype.onBlobsLoaded = function onBlobsLoaded(blobs) {
                var _this6 = this;

                var obsoleteBlobs = [];
                var updatedFiles = _extends({}, this.uppy.state.files);
                Object.keys(blobs).forEach(function (fileID) {
                    var originalFile = _this6.uppy.getFile(fileID);
                    if (!originalFile) {
                        obsoleteBlobs.push(fileID);
                        return;
                    }

                    var cachedData = blobs[fileID];

                    var updatedFileData = {
                        data: cachedData,
                        isRestored: true
                    };
                    var updatedFile = _extends({}, originalFile, updatedFileData);
                    updatedFiles[fileID] = updatedFile;

                    _this6.uppy.generatePreview(updatedFile);
                });

                this.uppy.setState({
                    files: updatedFiles
                });

                this.uppy.emit('restored', this.savedPluginData);

                if (obsoleteBlobs.length) {
                    this.deleteBlobs(obsoleteBlobs).then(function () {
                        _this6.uppy.log('[GoldenRetriever] Cleaned up ' + obsoleteBlobs.length + ' old files');
                    });
                }
            };

            GoldenRetriever.prototype.deleteBlobs = function deleteBlobs(fileIDs) {
                var _this7 = this;

                var promises = [];
                fileIDs.forEach(function (id) {
                    if (_this7.ServiceWorkerStore) {
                        promises.push(_this7.ServiceWorkerStore.delete(id));
                    }
                    if (_this7.IndexedDBStore) {
                        promises.push(_this7.IndexedDBStore.delete(id));
                    }
                });
                return _Promise.all(promises);
            };

            GoldenRetriever.prototype.install = function install() {
                var _this8 = this;

                this.loadFilesStateFromLocalStorage();

                if (Object.keys(this.uppy.state.files).length > 0) {
                    if (this.ServiceWorkerStore) {
                        this.uppy.log('[GoldenRetriever] Attempting to load files from Service Worker...');
                        this.loadFileBlobsFromServiceWorker();
                    } else {
                        this.uppy.log('[GoldenRetriever] Attempting to load files from Indexed DB...');
                        this.loadFileBlobsFromIndexedDB();
                    }
                } else {
                    this.uppy.log('[GoldenRetriever] No files need to be loaded, only restoring processing state...');
                    this.onBlobsLoaded([]);
                }

                this.uppy.on('file-added', function (file) {
                    if (file.isRemote) return;

                    if (_this8.ServiceWorkerStore) {
                        _this8.ServiceWorkerStore.put(file).catch(function (err) {
                            _this8.uppy.log('[GoldenRetriever] Could not store file', 'error');
                            _this8.uppy.log(err);
                        });
                    }

                    _this8.IndexedDBStore.put(file).catch(function (err) {
                        _this8.uppy.log('[GoldenRetriever] Could not store file', 'error');
                        _this8.uppy.log(err);
                    });
                });

                this.uppy.on('file-removed', function (fileID) {
                    if (_this8.ServiceWorkerStore) _this8.ServiceWorkerStore.delete(fileID);
                    _this8.IndexedDBStore.delete(fileID);
                });

                this.uppy.on('complete', function (_ref) {
                    var successful = _ref.successful;

                    var fileIDs = successful.map(function (file) {
                        return file.id;
                    });
                    _this8.deleteBlobs(fileIDs).then(function () {
                        _this8.uppy.log('[GoldenRetriever] Removed ' + successful.length + ' files that finished uploading');
                    });
                });

                this.uppy.on('state-update', this.saveFilesStateToLocalStorage);

                this.uppy.on('restored', function () {
                    // start all uploads again when file blobs are restored
                    var _uppy$getState = _this8.uppy.getState(),
                        currentUploads = _uppy$getState.currentUploads;

                    if (currentUploads) {
                        Object.keys(currentUploads).forEach(function (uploadId) {
                            _this8.uppy.restore(uploadId, currentUploads[uploadId]);
                        });
                    }
                });
            };

            return GoldenRetriever;
        }(Plugin);

    },{"../../core/Plugin":74,"./IndexedDBStore":96,"./MetaDataStore":97,"./ServiceWorkerStore":98,"es6-promise":33}],100:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../../core/Plugin');
        var Provider = require('../Provider');
        var View = require('../Provider/view');

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (_Plugin) {
            _inherits(GoogleDrive, _Plugin);

            function GoogleDrive(uppy, opts) {
                _classCallCheck(this, GoogleDrive);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'acquirer';
                _this.id = _this.opts.id || 'GoogleDrive';
                _this.title = 'Google Drive';
                _this.icon = function () {
                    return h(
                        'svg',
                        { 'aria-hidden': 'true', 'class': 'UppyIcon UppyModalTab-icon', width: '28', height: '28', viewBox: '0 0 16 16' },
                        h('path', { d: 'M2.955 14.93l2.667-4.62H16l-2.667 4.62H2.955zm2.378-4.62l-2.666 4.62L0 10.31l5.19-8.99 2.666 4.62-2.523 4.37zm10.523-.25h-5.333l-5.19-8.99h5.334l5.19 8.99z' })
                    );
                };

                _this[_this.id] = new Provider(uppy, {
                    host: _this.opts.host,
                    provider: 'drive',
                    authProvider: 'google'
                });

                _this.files = [];

                _this.onAuth = _this.onAuth.bind(_this);
                _this.render = _this.render.bind(_this);

                // set default options
                var defaultOptions = {};

                // merge default options with the ones set by user
                _this.opts = _extends({}, defaultOptions, opts);
                return _this;
            }

            GoogleDrive.prototype.install = function install() {
                this.view = new View(this);
                // Set default state for Google Drive
                this.setPluginState({
                    authenticated: false,
                    files: [],
                    folders: [],
                    directories: [],
                    activeRow: -1,
                    filterInput: '',
                    isSearchVisible: false
                });

                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }
            };

            GoogleDrive.prototype.uninstall = function uninstall() {
                this.view.tearDown();
                this.unmount();
            };

            GoogleDrive.prototype.onAuth = function onAuth(authenticated) {
                this.setPluginState({ authenticated: authenticated });
                if (authenticated) {
                    this.view.getFolder('root');
                }
            };

            GoogleDrive.prototype.isFolder = function isFolder(item) {
                return item.mimeType === 'application/vnd.google-apps.folder';
            };

            GoogleDrive.prototype.getItemData = function getItemData(item) {
                return _extends({}, item, { size: parseFloat(item.fileSize) });
            };

            GoogleDrive.prototype.getItemIcon = function getItemIcon(item) {
                return h('img', { src: item.iconLink });
            };

            GoogleDrive.prototype.getItemSubList = function getItemSubList(item) {
                var _this2 = this;

                return item.items.filter(function (i) {
                    return _this2.isFolder(i) || !i.mimeType.startsWith('application/vnd.google');
                });
            };

            GoogleDrive.prototype.getItemName = function getItemName(item) {
                return item.title ? item.title : '/';
            };

            GoogleDrive.prototype.getMimeType = function getMimeType(item) {
                return item.mimeType;
            };

            GoogleDrive.prototype.getItemId = function getItemId(item) {
                return item.id;
            };

            GoogleDrive.prototype.getItemRequestPath = function getItemRequestPath(item) {
                return this.getItemId(item);
            };

            GoogleDrive.prototype.getItemModifiedDate = function getItemModifiedDate(item) {
                return item.modifiedByMeDate;
            };

            GoogleDrive.prototype.getItemThumbnailUrl = function getItemThumbnailUrl(item) {
                return this.opts.host + '/' + this.GoogleDrive.id + '/thumbnail/' + this.getItemRequestPath(item);
            };

            GoogleDrive.prototype.render = function render(state) {
                return this.view.render(state);
            };

            return GoogleDrive;
        }(Plugin);

    },{"../../core/Plugin":74,"../Provider":104,"../Provider/view":113,"preact":46}],101:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../core/Plugin');

        var _require = require('preact'),
            h = _require.h;

        /**
         * Informer
         * Shows rad message bubbles
         * used like this: `uppy.info('hello world', 'info', 5000)`
         * or for errors: `uppy.info('Error uploading img.jpg', 'error', 5000)`
         *
         */


        module.exports = function (_Plugin) {
            _inherits(Informer, _Plugin);

            function Informer(uppy, opts) {
                _classCallCheck(this, Informer);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'progressindicator';
                _this.id = _this.opts.id || 'Informer';
                _this.title = 'Informer';

                // set default options
                var defaultOptions = {
                    typeColors: {
                        info: {
                            text: '#fff',
                            bg: '#000'
                        },
                        warning: {
                            text: '#fff',
                            bg: '#F6A623'
                        },
                        error: {
                            text: '#fff',
                            bg: '#e74c3c'
                        },
                        success: {
                            text: '#fff',
                            bg: '#7ac824'
                        }
                    }

                    // merge default options with the ones set by user
                };_this.opts = _extends({}, defaultOptions, opts);

                _this.render = _this.render.bind(_this);
                return _this;
            }

            Informer.prototype.render = function render(state) {
                var _state$info = state.info,
                    isHidden = _state$info.isHidden,
                    type = _state$info.type,
                    message = _state$info.message,
                    details = _state$info.details;

                var style = {
                    backgroundColor: this.opts.typeColors[type].bg,
                    color: this.opts.typeColors[type].text
                };

                return h(
                    'div',
                    { 'class': 'uppy uppy-Informer',
                        style: style,
                        'aria-hidden': isHidden },
                    h(
                        'p',
                        { role: 'alert' },
                        message,
                        ' ',
                        details && h(
                        'span',
                        { style: { color: this.opts.typeColors[type].bg },
                            'aria-label': details,
                            'data-microtip-position': 'top',
                            'data-microtip-size': 'large',
                            role: 'tooltip' },
                        '?'
                        )
                    )
                );
            };

            Informer.prototype.install = function install() {
                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }
            };

            return Informer;
        }(Plugin);

    },{"../core/Plugin":74,"preact":46}],102:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../../core/Plugin');
        var Provider = require('../Provider');
        var View = require('../Provider/view');

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (_Plugin) {
            _inherits(Instagram, _Plugin);

            function Instagram(uppy, opts) {
                _classCallCheck(this, Instagram);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'acquirer';
                _this.id = _this.opts.id || 'Instagram';
                _this.title = 'Instagram';
                _this.icon = function () {
                    return h(
                        'svg',
                        { 'aria-hidden': 'true', 'class': 'UppyIcon UppyModalTab-icon', width: '28', height: '28', viewBox: '0 0 512 512' },
                        h('path', { d: 'M256,49.471c67.266,0,75.233.257,101.8,1.469,24.562,1.121,37.9,5.224,46.778,8.674a78.052,78.052,0,0,1,28.966,18.845,78.052,78.052,0,0,1,18.845,28.966c3.45,8.877,7.554,22.216,8.674,46.778,1.212,26.565,1.469,34.532,1.469,101.8s-0.257,75.233-1.469,101.8c-1.121,24.562-5.225,37.9-8.674,46.778a83.427,83.427,0,0,1-47.811,47.811c-8.877,3.45-22.216,7.554-46.778,8.674-26.56,1.212-34.527,1.469-101.8,1.469s-75.237-.257-101.8-1.469c-24.562-1.121-37.9-5.225-46.778-8.674a78.051,78.051,0,0,1-28.966-18.845,78.053,78.053,0,0,1-18.845-28.966c-3.45-8.877-7.554-22.216-8.674-46.778-1.212-26.564-1.469-34.532-1.469-101.8s0.257-75.233,1.469-101.8c1.121-24.562,5.224-37.9,8.674-46.778A78.052,78.052,0,0,1,78.458,78.458a78.053,78.053,0,0,1,28.966-18.845c8.877-3.45,22.216-7.554,46.778-8.674,26.565-1.212,34.532-1.469,101.8-1.469m0-45.391c-68.418,0-77,.29-103.866,1.516-26.815,1.224-45.127,5.482-61.151,11.71a123.488,123.488,0,0,0-44.62,29.057A123.488,123.488,0,0,0,17.3,90.982C11.077,107.007,6.819,125.319,5.6,152.134,4.369,179,4.079,187.582,4.079,256S4.369,333,5.6,359.866c1.224,26.815,5.482,45.127,11.71,61.151a123.489,123.489,0,0,0,29.057,44.62,123.486,123.486,0,0,0,44.62,29.057c16.025,6.228,34.337,10.486,61.151,11.71,26.87,1.226,35.449,1.516,103.866,1.516s77-.29,103.866-1.516c26.815-1.224,45.127-5.482,61.151-11.71a128.817,128.817,0,0,0,73.677-73.677c6.228-16.025,10.486-34.337,11.71-61.151,1.226-26.87,1.516-35.449,1.516-103.866s-0.29-77-1.516-103.866c-1.224-26.815-5.482-45.127-11.71-61.151a123.486,123.486,0,0,0-29.057-44.62A123.487,123.487,0,0,0,421.018,17.3C404.993,11.077,386.681,6.819,359.866,5.6,333,4.369,324.418,4.079,256,4.079h0Z' }),
                        h('path', { d: 'M256,126.635A129.365,129.365,0,1,0,385.365,256,129.365,129.365,0,0,0,256,126.635Zm0,213.338A83.973,83.973,0,1,1,339.974,256,83.974,83.974,0,0,1,256,339.973Z' }),
                        h('circle', { cx: '390.476', cy: '121.524', r: '30.23' })
                    );
                };

                _this[_this.id] = new Provider(uppy, {
                    host: _this.opts.host,
                    provider: 'instagram',
                    authProvider: 'instagram'
                });

                _this.files = [];

                _this.onAuth = _this.onAuth.bind(_this);
                _this.render = _this.render.bind(_this);

                // set default options
                var defaultOptions = {};

                // merge default options with the ones set by user
                _this.opts = _extends({}, defaultOptions, opts);
                return _this;
            }

            Instagram.prototype.install = function install() {
                this.view = new View(this, {
                    viewType: 'grid'
                });
                // Set default state for Instagram
                this.setPluginState({
                    authenticated: false,
                    files: [],
                    folders: [],
                    directories: [],
                    activeRow: -1,
                    filterInput: '',
                    isSearchVisible: false
                });

                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }
            };

            Instagram.prototype.uninstall = function uninstall() {
                this.view.tearDown();
                this.unmount();
            };

            Instagram.prototype.onAuth = function onAuth(authenticated) {
                this.setPluginState({ authenticated: authenticated });
                if (authenticated) {
                    this.view.getFolder('recent');
                }
            };

            Instagram.prototype.isFolder = function isFolder(item) {
                return false;
            };

            Instagram.prototype.getItemData = function getItemData(item) {
                return item;
            };

            Instagram.prototype.getItemIcon = function getItemIcon(item) {
                return h('img', { src: item.images.thumbnail.url });
            };

            Instagram.prototype.getItemSubList = function getItemSubList(item) {
                var subItems = [];
                item.data.forEach(function (subItem) {
                    if (subItem.carousel_media) {
                        subItem.carousel_media.forEach(function (i, index) {
                            var id = subItem.id,
                                created_time = subItem.created_time;

                            var newSubItem = _extends({}, i, { id: id, created_time: created_time });
                            newSubItem.carousel_id = index;
                            subItems.push(newSubItem);
                        });
                    } else {
                        subItems.push(subItem);
                    }
                });
                return subItems;
            };

            Instagram.prototype.getItemName = function getItemName(item) {
                return '';
            };

            Instagram.prototype.getMimeType = function getMimeType(item) {
                return item.type === 'video' ? 'video/mp4' : 'image/jpeg';
            };

            Instagram.prototype.getItemId = function getItemId(item) {
                return '' + item.id + (item.carousel_id || '');
            };

            Instagram.prototype.getItemRequestPath = function getItemRequestPath(item) {
                var suffix = isNaN(item.carousel_id) ? '' : '?carousel_id=' + item.carousel_id;
                return '' + item.id + suffix;
            };

            Instagram.prototype.getItemModifiedDate = function getItemModifiedDate(item) {
                return item.created_time;
            };

            Instagram.prototype.getItemThumbnailUrl = function getItemThumbnailUrl(item) {
                return item.images.thumbnail.url;
            };

            Instagram.prototype.getNextPagePath = function getNextPagePath() {
                var _getPluginState = this.getPluginState(),
                    files = _getPluginState.files;

                return 'recent?max_id=' + this.getItemId(files[files.length - 1]);
            };

            Instagram.prototype.render = function render(state) {
                return this.view.render(state);
            };

            return Instagram;
        }(Plugin);

    },{"../../core/Plugin":74,"../Provider":104,"../Provider/view":113,"preact":46}],103:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../core/Plugin');

        var _require = require('preact'),
            h = _require.h;

        /**
         * Progress bar
         *
         */


        module.exports = function (_Plugin) {
            _inherits(ProgressBar, _Plugin);

            function ProgressBar(uppy, opts) {
                _classCallCheck(this, ProgressBar);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.id = _this.opts.id || 'ProgressBar';
                _this.title = 'Progress Bar';
                _this.type = 'progressindicator';

                // set default options
                var defaultOptions = {
                    target: 'body',
                    replaceTargetContent: false,
                    fixed: false,
                    hideAfterFinish: true

                    // merge default options with the ones set by user
                };_this.opts = _extends({}, defaultOptions, opts);

                _this.render = _this.render.bind(_this);
                return _this;
            }

            ProgressBar.prototype.render = function render(state) {
                var progress = state.totalProgress || 0;
                var isHidden = progress === 100 && this.opts.hideAfterFinish;
                return h(
                    'div',
                    { 'class': 'uppy uppy-ProgressBar', style: { position: this.opts.fixed ? 'fixed' : 'initial' }, 'aria-hidden': isHidden },
                    h('div', { 'class': 'uppy-ProgressBar-inner', style: { width: progress + '%' } }),
                    h(
                        'div',
                        { 'class': 'uppy-ProgressBar-percentage' },
                        progress
                    )
                );
            };

            ProgressBar.prototype.install = function install() {
                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }
            };

            ProgressBar.prototype.uninstall = function uninstall() {
                this.unmount();
            };

            return ProgressBar;
        }(Plugin);

    },{"../core/Plugin":74,"preact":46}],104:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        require('whatwg-fetch');

        var _getName = function _getName(id) {
            return id.split('-').map(function (s) {
                return s.charAt(0).toUpperCase() + s.slice(1);
            }).join(' ');
        };

        module.exports = function () {
            function Provider(uppy, opts) {
                _classCallCheck(this, Provider);

                this.uppy = uppy;
                this.opts = opts;
                this.provider = opts.provider;
                this.id = this.provider;
                this.authProvider = opts.authProvider || this.provider;
                this.name = this.opts.name || _getName(this.id);

                this.onReceiveResponse = this.onReceiveResponse.bind(this);
            }

            Provider.prototype.onReceiveResponse = function onReceiveResponse(response) {
                var uppyServer = this.uppy.state.uppyServer || {};
                var host = this.opts.host;
                var headers = response.headers;
                // Store the self-identified domain name for the uppy-server we just hit.
                if (headers.has('i-am') && headers.get('i-am') !== uppyServer[host]) {
                    var _extends2;

                    this.uppy.setState({
                        uppyServer: _extends({}, uppyServer, (_extends2 = {}, _extends2[host] = headers.get('i-am'), _extends2))
                    });
                }
                return response;
            };

            Provider.prototype.checkAuth = function checkAuth() {
                return fetch(this.hostname + '/' + this.id + '/authorized', {
                    method: 'get',
                    credentials: 'include',
                    headers: {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json'
                    }
                }).then(this.onReceiveResponse).then(function (res) {
                    return res.json().then(function (payload) {
                        return payload.authenticated;
                    });
                });
            };

            Provider.prototype.authUrl = function authUrl() {
                return this.hostname + '/' + this.id + '/connect';
            };

            Provider.prototype.fileUrl = function fileUrl(id) {
                return this.hostname + '/' + this.id + '/get/' + id;
            };

            Provider.prototype.list = function list(directory) {
                return fetch(this.hostname + '/' + this.id + '/list/' + (directory || ''), {
                    method: 'get',
                    credentials: 'include',
                    headers: {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json'
                    }
                }).then(this.onReceiveResponse).then(function (res) {
                    return res.json();
                });
            };

            Provider.prototype.logout = function logout() {
                var redirect = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : location.href;

                return fetch(this.hostname + '/' + this.id + '/logout?redirect=' + redirect, {
                    method: 'get',
                    credentials: 'include',
                    headers: {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json'
                    }
                });
            };

            _createClass(Provider, [{
                key: 'hostname',
                get: function get() {
                    var uppyServer = this.uppy.state.uppyServer || {};
                    var host = this.opts.host;
                    return uppyServer[host] || host;
                }
            }]);

            return Provider;
        }();

    },{"whatwg-fetch":70}],105:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var LoaderView = require('./Loader');

        var _require = require('preact'),
            h = _require.h,
            Component = _require.Component;

        var AuthView = function (_Component) {
            _inherits(AuthView, _Component);

            function AuthView() {
                _classCallCheck(this, AuthView);

                return _possibleConstructorReturn(this, _Component.apply(this, arguments));
            }

            AuthView.prototype.componentDidMount = function componentDidMount() {
                this.props.checkAuth();
            };

            AuthView.prototype.render = function render() {
                var _this2 = this;

                var AuthBlock = function AuthBlock() {
                    return h(
                        'div',
                        { 'class': 'uppy-Provider-auth' },
                        h(
                            'h1',
                            { 'class': 'uppy-Provider-authTitle' },
                            'Please authenticate with ',
                            h(
                                'span',
                                { 'class': 'uppy-Provider-authTitleName' },
                                _this2.props.pluginName
                            ),
                            h('br', null),
                            ' to select files'
                        ),
                        h(
                            'button',
                            { type: 'button', 'class': 'uppy-Provider-authBtn', onclick: _this2.props.handleAuth },
                            'Connect to ',
                            _this2.props.pluginName
                        ),
                        _this2.props.demo && h(
                        'button',
                        { 'class': 'uppy-Provider-authBtnDemo', onclick: _this2.props.handleDemoAuth },
                        'Proceed with Demo Account'
                        )
                    );
                };

                return h(
                    'div',
                    { style: 'height: 100%;' },
                    this.props.checkAuthInProgress ? LoaderView() : AuthBlock()
                );
            };

            return AuthView;
        }(Component);

        module.exports = AuthView;

    },{"./Loader":110,"preact":46}],106:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            return h(
                "li",
                null,
                h(
                    "button",
                    { type: "button", onclick: props.getFolder },
                    props.title
                )
            );
        };

    },{"preact":46}],107:[function(require,module,exports){
        'use strict';

        var _require = require('preact'),
            h = _require.h;

        var Breadcrumb = require('./Breadcrumb');

        module.exports = function (props) {
            return h(
                'ul',
                { 'class': 'uppy-Provider-breadcrumbs' },
                props.directories.map(function (directory, i) {
                    return Breadcrumb({
                        getFolder: function getFolder() {
                            return props.getFolder(directory.id);
                        },
                        title: i === 0 ? props.title : directory.title
                    });
                })
            );
        };

    },{"./Breadcrumb":106,"preact":46}],108:[function(require,module,exports){
        'use strict';

        var Breadcrumbs = require('./Breadcrumbs');
        var Filter = require('./Filter');
        var Table = require('./Table');

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            var filteredFolders = props.folders;
            var filteredFiles = props.files;

            if (props.filterInput !== '') {
                filteredFolders = props.filterItems(props.folders);
                filteredFiles = props.filterItems(props.files);
            }

            return h(
                'div',
                { 'class': 'uppy uppy-ProviderBrowser uppy-ProviderBrowser-viewType--' + props.viewType },
                h(
                    'header',
                    { 'class': 'uppy-ProviderBrowser-header' },
                    h(
                        'div',
                        { 'class': 'uppy-ProviderBrowser-search', 'aria-hidden': !props.isSearchVisible },
                        props.isSearchVisible && h(Filter, props)
                    ),
                    h(
                        'div',
                        { 'class': 'uppy-ProviderBrowser-headerBar' },
                        h(
                            'button',
                            { type: 'button', 'class': 'uppy-ProviderBrowser-searchToggle',
                                onclick: props.toggleSearch },
                            h(
                                'svg',
                                { 'class': 'UppyIcon', viewBox: '0 0 100 100' },
                                h('path', { d: 'M87.533 80.03L62.942 55.439c3.324-4.587 5.312-10.207 5.312-16.295 0-.312-.043-.611-.092-.908.05-.301.093-.605.093-.922 0-15.36-12.497-27.857-27.857-27.857-.273 0-.536.043-.799.08-.265-.037-.526-.08-.799-.08-15.361 0-27.858 12.497-27.858 27.857 0 .312.042.611.092.909a5.466 5.466 0 0 0-.093.921c0 15.36 12.496 27.858 27.857 27.858.273 0 .535-.043.8-.081.263.038.524.081.798.081 5.208 0 10.071-1.464 14.245-3.963L79.582 87.98a5.603 5.603 0 0 0 3.976 1.647 5.621 5.621 0 0 0 3.975-9.597zM39.598 55.838c-.265-.038-.526-.081-.8-.081-9.16 0-16.612-7.452-16.612-16.612 0-.312-.042-.611-.092-.908.051-.301.093-.605.093-.922 0-9.16 7.453-16.612 16.613-16.612.272 0 .534-.042.799-.079.263.037.525.079.799.079 9.16 0 16.612 7.452 16.612 16.612 0 .312.043.611.092.909-.05.301-.094.604-.094.921 0 9.16-7.452 16.612-16.612 16.612-.274 0-.536.043-.798.081z' })
                            )
                        ),
                        Breadcrumbs({
                            getFolder: props.getFolder,
                            directories: props.directories,
                            title: props.title
                        }),
                        h(
                            'button',
                            { type: 'button', onclick: props.logout, 'class': 'uppy-ProviderBrowser-userLogout' },
                            'Log out'
                        )
                    )
                ),
                Table({
                    columns: [{
                        name: 'Name',
                        key: 'title'
                    }],
                    folders: filteredFolders,
                    files: filteredFiles,
                    activeRow: props.isActiveRow,
                    sortByTitle: props.sortByTitle,
                    sortByDate: props.sortByDate,
                    handleFileClick: props.addFile,
                    handleFolderClick: props.getNextFolder,
                    isChecked: props.isChecked,
                    toggleCheckbox: props.toggleCheckbox,
                    getItemName: props.getItemName,
                    getItemIcon: props.getItemIcon,
                    handleScroll: props.handleScroll,
                    title: props.title
                }),
                h(
                    'button',
                    { 'class': 'UppyButton--circular UppyButton--blue uppy-ProviderBrowser-doneBtn',
                        type: 'button',
                        'aria-label': 'Done picking files',
                        title: 'Done picking files',
                        onclick: props.done },
                    h(
                        'svg',
                        { 'aria-hidden': 'true', 'class': 'UppyIcon', width: '13px', height: '9px', viewBox: '0 0 13 9' },
                        h('polygon', { points: '5 7.293 1.354 3.647 0.646 4.354 5 8.707 12.354 1.354 11.646 0.647' })
                    )
                )
            );
        };

    },{"./Breadcrumbs":107,"./Filter":109,"./Table":111,"preact":46}],109:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _require = require('preact'),
            h = _require.h,
            Component = _require.Component;

        module.exports = function (_Component) {
            _inherits(Filter, _Component);

            function Filter(props) {
                _classCallCheck(this, Filter);

                var _this = _possibleConstructorReturn(this, _Component.call(this, props));

                _this.handleKeyPress = _this.handleKeyPress.bind(_this);
                return _this;
            }

            Filter.prototype.componentDidMount = function componentDidMount() {
                this.input.focus();
            };

            Filter.prototype.handleKeyPress = function handleKeyPress(ev) {
                if (ev.keyCode === 13) {
                    ev.stopPropagation();
                    ev.preventDefault();
                    return;
                }
                this.props.filterQuery(ev);
            };

            Filter.prototype.render = function render() {
                var _this2 = this;

                return h(
                    'div',
                    { style: { display: 'flex', width: '100%' } },
                    h('input', {
                        'class': 'uppy-ProviderBrowser-searchInput',
                        type: 'text',
                        placeholder: 'Search',
                        onkeyup: this.handleKeyPress,
                        onkeydown: this.handleKeyPress,
                        onkeypress: this.handleKeyPress,
                        value: this.props.filterInput,
                        ref: function ref(input) {
                            _this2.input = input;
                        } }),
                    h(
                        'button',
                        {
                            'class': 'uppy-ProviderBrowser-searchClose',
                            type: 'button',
                            onclick: this.props.toggleSearch },
                        h(
                            'svg',
                            { 'class': 'UppyIcon', viewBox: '0 0 19 19' },
                            h('path', { d: 'M17.318 17.232L9.94 9.854 9.586 9.5l-.354.354-7.378 7.378h.707l-.62-.62v.706L9.318 9.94l.354-.354-.354-.354L1.94 1.854v.707l.62-.62h-.706l7.378 7.378.354.354.354-.354 7.378-7.378h-.707l.622.62v-.706L9.854 9.232l-.354.354.354.354 7.378 7.378.708-.707-7.38-7.378v.708l7.38-7.38.353-.353-.353-.353-.622-.622-.353-.353-.354.352-7.378 7.38h.708L2.56 1.23 2.208.88l-.353.353-.622.62-.353.355.352.353 7.38 7.38v-.708l-7.38 7.38-.353.353.352.353.622.622.353.353.354-.353 7.38-7.38h-.708l7.38 7.38z' })
                        )
                    )
                );
            };

            return Filter;
        }(Component);

    },{"preact":46}],110:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            return h(
                "div",
                { "class": "uppy-Provider-loading" },
                h(
                    "span",
                    null,
                    "Loading..."
                )
            );
        };

    },{"preact":46}],111:[function(require,module,exports){
        'use strict';

        var Row = require('./TableRow');

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            // const headers = props.columns.map((column) => {
            //   return html`
            //     <th class="uppy-ProviderBrowserTable-headerColumn uppy-ProviderBrowserTable-column" onclick=${props.sortByTitle}>
            //       ${column.name}
            //     </th>
            //   `
            // })

            // <thead class="uppy-ProviderBrowserTable-header">
            //   <tr>${headers}</tr>
            // </thead>

            return h(
                'div',
                { 'class': 'uppy-ProviderBrowser-body' },
                h(
                    'ul',
                    { 'class': 'uppy-ProviderBrowser-list',
                        onscroll: props.handleScroll,
                        role: 'listbox',
                        'aria-label': 'List of files from ' + props.title },
                    props.folders.map(function (folder) {
                        var isDisabled = false;
                        var isChecked = props.isChecked(folder);
                        if (isChecked) {
                            isDisabled = isChecked.loading;
                        }
                        return Row({
                            title: props.getItemName(folder),
                            type: 'folder',
                            // active: props.activeRow(folder),
                            getItemIcon: function getItemIcon() {
                                return props.getItemIcon(folder);
                            },
                            handleClick: function handleClick() {
                                return props.handleFolderClick(folder);
                            },
                            isDisabled: isDisabled,
                            isChecked: isChecked,
                            handleCheckboxClick: function handleCheckboxClick(e) {
                                return props.toggleCheckbox(e, folder);
                            },
                            columns: props.columns
                        });
                    }),
                    props.files.map(function (file) {
                        return Row({
                            title: props.getItemName(file),
                            type: 'file',
                            // active: props.activeRow(file),
                            getItemIcon: function getItemIcon() {
                                return props.getItemIcon(file);
                            },
                            handleClick: function handleClick() {
                                return props.handleFileClick(file);
                            },
                            isDisabled: false,
                            isChecked: props.isChecked(file),
                            handleCheckboxClick: function handleCheckboxClick(e) {
                                return props.toggleCheckbox(e, file);
                            },
                            columns: props.columns
                        });
                    })
                )
            );
        };

    },{"./TableRow":112,"preact":46}],112:[function(require,module,exports){
        'use strict';

        var cuid = require('cuid');

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            var uniqueId = cuid();

            var stop = function stop(ev) {
                if (ev.keyCode === 13) {
                    ev.stopPropagation();
                    ev.preventDefault();
                }
            };

            var handleItemClick = function handleItemClick(ev) {
                ev.preventDefault();
                // when file is clicked, select it, but when folder is clicked, open it
                if (props.type === 'folder') {
                    return props.handleClick(ev);
                }
                props.handleCheckboxClick(ev);
            };

            return h(
                'li',
                { 'class': 'uppy-ProviderBrowserItem' + (props.isChecked ? ' uppy-ProviderBrowserItem--selected' : '') },
                h(
                    'div',
                    { 'class': 'uppy-ProviderBrowserItem-checkbox' },
                    h('input', { type: 'checkbox',
                        role: 'option',
                        tabindex: '0',
                        'aria-label': 'Select ' + props.title,
                        id: uniqueId,
                        checked: props.isChecked,
                        disabled: props.isDisabled,
                        onchange: props.handleCheckboxClick,
                        onkeyup: stop,
                        onkeydown: stop,
                        onkeypress: stop }),
                    h('label', { 'for': uniqueId })
                ),
                h(
                    'button',
                    { type: 'button',
                        'class': 'uppy-ProviderBrowserItem-inner',
                        'aria-label': 'Select ' + props.title,
                        tabindex: '0',
                        onclick: handleItemClick },
                    props.getItemIcon(),
                    ' ',
                    props.title
                )
            );
        };

    },{"cuid":11,"preact":46}],113:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var AuthView = require('./AuthView');
        var Browser = require('./Browser');
        var LoaderView = require('./Loader');
        var Utils = require('../../../core/Utils');

        var _require = require('preact'),
            h = _require.h;

        /**
         * Class to easily generate generic views for plugins
         *
         *
         * This class expects the plugin instance using it to have the following
         * accessor methods.
         * Each method takes the item whose property is to be accessed
         * as a param
         *
         * isFolder
         *    @return {Boolean} for if the item is a folder or not
         * getItemData
         *    @return {Object} that is format ready for uppy upload/download
         * getItemIcon
         *    @return {Object} html instance of the item's icon
         * getItemSubList
         *    @return {Array} sub-items in the item. e.g a folder may contain sub-items
         * getItemName
         *    @return {String} display friendly name of the item
         * getMimeType
         *    @return {String} mime type of the item
         * getItemId
         *    @return {String} unique id of the item
         * getItemRequestPath
         *    @return {String} unique request path of the item when making calls to uppy server
         * getItemModifiedDate
         *    @return {object} or {String} date of when last the item was modified
         * getItemThumbnailUrl
         *    @return {String}
         */


        module.exports = function () {
            /**
             * @param {object} instance of the plugin
             */
            function View(plugin, opts) {
                _classCallCheck(this, View);

                this.plugin = plugin;
                this.Provider = plugin[plugin.id];

                // set default options
                var defaultOptions = {
                    viewType: 'list'

                    // merge default options with the ones set by user
                };this.opts = _extends({}, defaultOptions, opts);

                // Logic
                this.updateFolderState = this.updateFolderState.bind(this);
                this.addFile = this.addFile.bind(this);
                this.filterItems = this.filterItems.bind(this);
                this.filterQuery = this.filterQuery.bind(this);
                this.toggleSearch = this.toggleSearch.bind(this);
                this.getFolder = this.getFolder.bind(this);
                this.getNextFolder = this.getNextFolder.bind(this);
                this.logout = this.logout.bind(this);
                this.checkAuth = this.checkAuth.bind(this);
                this.handleAuth = this.handleAuth.bind(this);
                this.handleDemoAuth = this.handleDemoAuth.bind(this);
                this.sortByTitle = this.sortByTitle.bind(this);
                this.sortByDate = this.sortByDate.bind(this);
                this.isActiveRow = this.isActiveRow.bind(this);
                this.isChecked = this.isChecked.bind(this);
                this.toggleCheckbox = this.toggleCheckbox.bind(this);
                this.handleError = this.handleError.bind(this);
                this.handleScroll = this.handleScroll.bind(this);
                this.donePicking = this.donePicking.bind(this);

                this.plugin.uppy.on('file-removed', this.updateFolderState);

                // Visual
                this.render = this.render.bind(this);
            }

            View.prototype.tearDown = function tearDown() {
                this.plugin.uppy.off('file-removed', this.updateFolderState);
            };

            View.prototype._updateFilesAndFolders = function _updateFilesAndFolders(res, files, folders) {
                var _this = this;

                this.plugin.getItemSubList(res).forEach(function (item) {
                    if (_this.plugin.isFolder(item)) {
                        folders.push(item);
                    } else {
                        files.push(item);
                    }
                });

                this.plugin.setPluginState({ folders: folders, files: files });
            };

            View.prototype.checkAuth = function checkAuth() {
                var _this2 = this;

                this.plugin.setPluginState({ checkAuthInProgress: true });
                this.Provider.checkAuth().then(function (authenticated) {
                    _this2.plugin.setPluginState({ checkAuthInProgress: false });
                    _this2.plugin.onAuth(authenticated);
                }).catch(function (err) {
                    _this2.plugin.setPluginState({ checkAuthInProgress: false });
                    _this2.handleError(err);
                });
            };

            /**
             * Based on folder ID, fetch a new folder and update it to state
             * @param  {String} id Folder id
             * @return {Promise}   Folders/files in folder
             */


            View.prototype.getFolder = function getFolder(id, name) {
                var _this3 = this;

                return this._loaderWrapper(this.Provider.list(id), function (res) {
                    var folders = [];
                    var files = [];
                    var updatedDirectories = void 0;

                    var state = _this3.plugin.getPluginState();
                    var index = state.directories.findIndex(function (dir) {
                        return id === dir.id;
                    });

                    if (index !== -1) {
                        updatedDirectories = state.directories.slice(0, index + 1);
                    } else {
                        updatedDirectories = state.directories.concat([{ id: id, title: name || _this3.plugin.getItemName(res) }]);
                    }

                    _this3._updateFilesAndFolders(res, files, folders);
                    _this3.plugin.setPluginState({ directories: updatedDirectories });
                }, this.handleError);
            };

            /**
             * Fetches new folder
             * @param  {Object} Folder
             * @param  {String} title Folder title
             */


            View.prototype.getNextFolder = function getNextFolder(folder) {
                var id = this.plugin.getItemRequestPath(folder);
                this.getFolder(id, this.plugin.getItemName(folder));
                this.lastCheckbox = undefined;
            };

            View.prototype.addFile = function addFile(file) {
                var _this4 = this;

                var isCheckbox = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

                var tagFile = {
                    source: this.plugin.id,
                    data: this.plugin.getItemData(file),
                    name: this.plugin.getItemName(file) || this.plugin.getItemId(file),
                    type: this.plugin.getMimeType(file),
                    isRemote: true,
                    body: {
                        fileId: this.plugin.getItemId(file)
                    },
                    remote: {
                        host: this.plugin.opts.host,
                        url: '' + this.Provider.fileUrl(this.plugin.getItemRequestPath(file)),
                        body: {
                            fileId: this.plugin.getItemId(file)
                        }
                    }
                };

                Utils.getFileType(tagFile).then(function (fileType) {
                    if (fileType && Utils.isPreviewSupported(fileType)) {
                        tagFile.preview = _this4.plugin.getItemThumbnailUrl(file);
                    }
                    _this4.plugin.uppy.log('Adding remote file');
                    _this4.plugin.uppy.addFile(tagFile).catch(function () {
                        // Ignore
                    });
                    if (!isCheckbox) {
                        _this4.donePicking();
                    }
                });
            };

            /**
             * Removes session token on client side.
             */


            View.prototype.logout = function logout() {
                var _this5 = this;

                this.Provider.logout(location.href).then(function (res) {
                    return res.json();
                }).then(function (res) {
                    if (res.ok) {
                        var newState = {
                            authenticated: false,
                            files: [],
                            folders: [],
                            directories: []
                        };
                        _this5.plugin.setPluginState(newState);
                    }
                }).catch(this.handleError);
            };

            View.prototype.filterQuery = function filterQuery(e) {
                var state = this.plugin.getPluginState();
                this.plugin.setPluginState(_extends({}, state, {
                    filterInput: e.target.value
                }));
            };

            View.prototype.toggleSearch = function toggleSearch(inputEl) {
                var state = this.plugin.getPluginState();

                this.plugin.setPluginState({
                    isSearchVisible: !state.isSearchVisible,
                    filterInput: ''
                });
            };

            View.prototype.filterItems = function filterItems(items) {
                var _this6 = this;

                var state = this.plugin.getPluginState();
                return items.filter(function (folder) {
                    return _this6.plugin.getItemName(folder).toLowerCase().indexOf(state.filterInput.toLowerCase()) !== -1;
                });
            };

            View.prototype.sortByTitle = function sortByTitle() {
                var _this7 = this;

                var state = _extends({}, this.plugin.getPluginState());
                var files = state.files,
                    folders = state.folders,
                    sorting = state.sorting;


                var sortedFiles = files.sort(function (fileA, fileB) {
                    if (sorting === 'titleDescending') {
                        return _this7.plugin.getItemName(fileB).localeCompare(_this7.plugin.getItemName(fileA));
                    }
                    return _this7.plugin.getItemName(fileA).localeCompare(_this7.plugin.getItemName(fileB));
                });

                var sortedFolders = folders.sort(function (folderA, folderB) {
                    if (sorting === 'titleDescending') {
                        return _this7.plugin.getItemName(folderB).localeCompare(_this7.plugin.getItemName(folderA));
                    }
                    return _this7.plugin.getItemName(folderA).localeCompare(_this7.plugin.getItemName(folderB));
                });

                this.plugin.setPluginState(_extends({}, state, {
                    files: sortedFiles,
                    folders: sortedFolders,
                    sorting: sorting === 'titleDescending' ? 'titleAscending' : 'titleDescending'
                }));
            };

            View.prototype.sortByDate = function sortByDate() {
                var _this8 = this;

                var state = _extends({}, this.plugin.getPluginState());
                var files = state.files,
                    folders = state.folders,
                    sorting = state.sorting;


                var sortedFiles = files.sort(function (fileA, fileB) {
                    var a = new Date(_this8.plugin.getItemModifiedDate(fileA));
                    var b = new Date(_this8.plugin.getItemModifiedDate(fileB));

                    if (sorting === 'dateDescending') {
                        return a > b ? -1 : a < b ? 1 : 0;
                    }
                    return a > b ? 1 : a < b ? -1 : 0;
                });

                var sortedFolders = folders.sort(function (folderA, folderB) {
                    var a = new Date(_this8.plugin.getItemModifiedDate(folderA));
                    var b = new Date(_this8.plugin.getItemModifiedDate(folderB));

                    if (sorting === 'dateDescending') {
                        return a > b ? -1 : a < b ? 1 : 0;
                    }

                    return a > b ? 1 : a < b ? -1 : 0;
                });

                this.plugin.setPluginState(_extends({}, state, {
                    files: sortedFiles,
                    folders: sortedFolders,
                    sorting: sorting === 'dateDescending' ? 'dateAscending' : 'dateDescending'
                }));
            };

            View.prototype.sortBySize = function sortBySize() {
                var _this9 = this;

                var state = _extends({}, this.plugin.getPluginState());
                var files = state.files,
                    sorting = state.sorting;

                // check that plugin supports file sizes

                if (!files.length || !this.plugin.getItemData(files[0]).size) {
                    return;
                }

                var sortedFiles = files.sort(function (fileA, fileB) {
                    var a = _this9.plugin.getItemData(fileA).size;
                    var b = _this9.plugin.getItemData(fileB).size;

                    if (sorting === 'sizeDescending') {
                        return a > b ? -1 : a < b ? 1 : 0;
                    }
                    return a > b ? 1 : a < b ? -1 : 0;
                });

                this.plugin.setPluginState(_extends({}, state, {
                    files: sortedFiles,
                    sorting: sorting === 'sizeDescending' ? 'sizeAscending' : 'sizeDescending'
                }));
            };

            View.prototype.isActiveRow = function isActiveRow(file) {
                return this.plugin.getPluginState().activeRow === this.plugin.getItemId(file);
            };

            View.prototype.isChecked = function isChecked(item) {
                var itemId = this.providerFileToId(item);
                if (this.plugin.isFolder(item)) {
                    var state = this.plugin.getPluginState();
                    var folders = state.selectedFolders || {};
                    if (itemId in folders) {
                        return folders[itemId];
                    }
                    return false;
                }
                return itemId in this.plugin.uppy.getState().files;
            };

            /**
             * Adds all files found inside of specified folder.
             *
             * Uses separated state while folder contents are being fetched and
             * mantains list of selected folders, which are separated from files.
             */


            View.prototype.addFolder = function addFolder(folder) {
                var _this10 = this;

                var folderId = this.providerFileToId(folder);
                var state = this.plugin.getPluginState();
                var folders = state.selectedFolders || {};
                if (folderId in folders && folders[folderId].loading) {
                    return;
                }
                folders[folderId] = { loading: true, files: [] };
                this.plugin.setPluginState({ selectedFolders: folders });
                this.Provider.list(this.plugin.getItemRequestPath(folder)).then(function (res) {
                    var files = [];
                    _this10.plugin.getItemSubList(res).forEach(function (item) {
                        if (!_this10.plugin.isFolder(item)) {
                            _this10.addFile(item, true);
                            files.push(_this10.providerFileToId(item));
                        }
                    });
                    state = _this10.plugin.getPluginState();
                    state.selectedFolders[folderId] = { loading: false, files: files };
                    _this10.plugin.setPluginState({ selectedFolders: folders });
                    var dashboard = _this10.plugin.uppy.getPlugin('Dashboard');
                    var message = void 0;
                    if (files.length) {
                        message = dashboard.i18n('folderAdded', {
                            smart_count: files.length, folder: _this10.plugin.getItemName(folder)
                        });
                    } else {
                        message = dashboard.i18n('emptyFolderAdded');
                    }
                    _this10.plugin.uppy.info(message);
                }).catch(function (e) {
                    state = _this10.plugin.getPluginState();
                    delete state.selectedFolders[folderId];
                    _this10.plugin.setPluginState({ selectedFolders: state.selectedFolders });
                    _this10.handleError(e);
                });
            };

            View.prototype.removeFolder = function removeFolder(folderId) {
                var state = this.plugin.getPluginState();
                var folders = state.selectedFolders || {};
                if (!(folderId in folders)) {
                    return;
                }
                var folder = folders[folderId];
                if (folder.loading) {
                    return;
                }
                // deepcopy the files before iteration because the
                // original array constantly gets mutated during
                // the iteration by updateFolderState as each file
                // is removed and 'core:file-removed' is emitted.
                var files = folder.files.concat([]);
                for (var _iterator = files, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
                    var _ref;

                    if (_isArray) {
                        if (_i >= _iterator.length) break;
                        _ref = _iterator[_i++];
                    } else {
                        _i = _iterator.next();
                        if (_i.done) break;
                        _ref = _i.value;
                    }

                    var fileId = _ref;

                    if (fileId in this.plugin.uppy.getState().files) {
                        this.plugin.uppy.removeFile(fileId);
                    }
                }
                delete folders[folderId];
                this.plugin.setPluginState({ selectedFolders: folders });
            };

            /**
             * Updates selected folders state everytime file is being removed.
             *
             * Note that this is only important when files are getting removed from the
             * main screen, and will do nothing when you uncheck folder directly, since
             * it's already been done in removeFolder method.
             */


            View.prototype.updateFolderState = function updateFolderState(fileId) {
                var state = this.plugin.getPluginState();
                var folders = state.selectedFolders || {};
                for (var folderId in folders) {
                    var folder = folders[folderId];
                    if (folder.loading) {
                        continue;
                    }
                    var i = folder.files.indexOf(fileId);
                    if (i > -1) {
                        folder.files.splice(i, 1);
                    }
                    if (!folder.files.length) {
                        delete folders[folderId];
                    }
                }
                this.plugin.setPluginState({ selectedFolders: folders });
            };

            /**
             * Toggles file/folder checkbox to on/off state while updating files list.
             *
             * Note that some extra complexity comes from supporting shift+click to
             * toggle multiple checkboxes at once, which is done by getting all files
             * in between last checked file and current one, and applying an on/off state
             * for all of them, depending on current file state.
             */


            View.prototype.toggleCheckbox = function toggleCheckbox(e, file) {
                e.stopPropagation();
                e.preventDefault();

                var _plugin$getPluginStat = this.plugin.getPluginState(),
                    folders = _plugin$getPluginStat.folders,
                    files = _plugin$getPluginStat.files,
                    filterInput = _plugin$getPluginStat.filterInput;

                var items = folders.concat(files);
                if (filterInput !== '') {
                    items = this.filterItems(items);
                }
                var itemsToToggle = [file];
                if (this.lastCheckbox && e.shiftKey) {
                    var prevIndex = items.indexOf(this.lastCheckbox);
                    var currentIndex = items.indexOf(file);
                    if (prevIndex < currentIndex) {
                        itemsToToggle = items.slice(prevIndex, currentIndex + 1);
                    } else {
                        itemsToToggle = items.slice(currentIndex, prevIndex + 1);
                    }
                }
                this.lastCheckbox = file;
                if (this.isChecked(file)) {
                    for (var _iterator2 = itemsToToggle, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
                        var _ref2;

                        if (_isArray2) {
                            if (_i2 >= _iterator2.length) break;
                            _ref2 = _iterator2[_i2++];
                        } else {
                            _i2 = _iterator2.next();
                            if (_i2.done) break;
                            _ref2 = _i2.value;
                        }

                        var item = _ref2;

                        var itemId = this.providerFileToId(item);
                        if (this.plugin.isFolder(item)) {
                            this.removeFolder(itemId);
                        } else {
                            if (itemId in this.plugin.uppy.getState().files) {
                                this.plugin.uppy.removeFile(itemId);
                            }
                        }
                    }
                } else {
                    for (var _iterator3 = itemsToToggle, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
                        var _ref3;

                        if (_isArray3) {
                            if (_i3 >= _iterator3.length) break;
                            _ref3 = _iterator3[_i3++];
                        } else {
                            _i3 = _iterator3.next();
                            if (_i3.done) break;
                            _ref3 = _i3.value;
                        }

                        var _item = _ref3;

                        if (this.plugin.isFolder(_item)) {
                            this.addFolder(_item);
                        } else {
                            this.addFile(_item, true);
                        }
                    }
                }
            };

            View.prototype.providerFileToId = function providerFileToId(file) {
                return Utils.generateFileID({
                    data: this.plugin.getItemData(file),
                    name: this.plugin.getItemName(file) || this.plugin.getItemId(file),
                    type: this.plugin.getMimeType(file)
                });
            };

            View.prototype.handleDemoAuth = function handleDemoAuth() {
                var state = this.plugin.getPluginState();
                this.plugin.setPluginState({}, state, {
                    authenticated: true
                });
            };

            View.prototype.handleAuth = function handleAuth() {
                var _this11 = this;

                var urlId = Math.floor(Math.random() * 999999) + 1;
                var redirect = '' + location.href + (location.search ? '&' : '?') + 'id=' + urlId;

                var authState = btoa(JSON.stringify({ redirect: redirect }));
                var link = this.Provider.authUrl() + '?state=' + authState;

                var authWindow = window.open(link, '_blank');
                var checkAuth = function checkAuth() {
                    var authWindowUrl = void 0;

                    try {
                        authWindowUrl = authWindow.location.href;
                    } catch (e) {
                        if (e instanceof DOMException || e instanceof TypeError) {
                            return setTimeout(checkAuth, 100);
                        } else throw e;
                    }

                    // split url because chrome adds '#' to redirects
                    if (authWindowUrl && authWindowUrl.split('#')[0] === redirect) {
                        authWindow.close();
                        _this11._loaderWrapper(_this11.Provider.checkAuth(), _this11.plugin.onAuth, _this11.handleError);
                    } else {
                        setTimeout(checkAuth, 100);
                    }
                };

                checkAuth();
            };

            View.prototype.handleError = function handleError(error) {
                var uppy = this.plugin.uppy;
                var message = uppy.i18n('uppyServerError');
                uppy.log(error.toString());
                uppy.info({ message: message, details: error.toString() }, 'error', 5000);
            };

            View.prototype.handleScroll = function handleScroll(e) {
                var _this12 = this;

                var scrollPos = e.target.scrollHeight - (e.target.scrollTop + e.target.offsetHeight);
                var path = this.plugin.getNextPagePath ? this.plugin.getNextPagePath() : null;

                if (scrollPos < 50 && path && !this._isHandlingScroll) {
                    this.Provider.list(path).then(function (res) {
                        var _plugin$getPluginStat2 = _this12.plugin.getPluginState(),
                            files = _plugin$getPluginStat2.files,
                            folders = _plugin$getPluginStat2.folders;

                        _this12._updateFilesAndFolders(res, files, folders);
                    }).catch(this.handleError).then(function () {
                        _this12._isHandlingScroll = false;
                    }); // always called

                    this._isHandlingScroll = true;
                }
            };

            View.prototype.donePicking = function donePicking() {
                var dashboard = this.plugin.uppy.getPlugin('Dashboard');
                if (dashboard) dashboard.hideAllPanels();
            };

            // displays loader view while asynchronous request is being made.


            View.prototype._loaderWrapper = function _loaderWrapper(promise, then, catch_) {
                var _this13 = this;

                promise.then(then).catch(catch_).then(function () {
                    return _this13.plugin.setPluginState({ loading: false });
                }); // always called.
                this.plugin.setPluginState({ loading: true });
            };

            View.prototype.render = function render(state) {
                var _plugin$getPluginStat3 = this.plugin.getPluginState(),
                    authenticated = _plugin$getPluginStat3.authenticated,
                    checkAuthInProgress = _plugin$getPluginStat3.checkAuthInProgress,
                    loading = _plugin$getPluginStat3.loading;

                if (loading) {
                    return LoaderView();
                }

                if (!authenticated) {
                    return h(AuthView, {
                        pluginName: this.plugin.title,
                        demo: this.plugin.opts.demo,
                        checkAuth: this.checkAuth,
                        handleAuth: this.handleAuth,
                        handleDemoAuth: this.handleDemoAuth,
                        checkAuthInProgress: checkAuthInProgress
                    });
                }

                var browserProps = _extends({}, this.plugin.getPluginState(), {
                    getNextFolder: this.getNextFolder,
                    getFolder: this.getFolder,
                    addFile: this.addFile,
                    filterItems: this.filterItems,
                    filterQuery: this.filterQuery,
                    toggleSearch: this.toggleSearch,
                    sortByTitle: this.sortByTitle,
                    sortByDate: this.sortByDate,
                    logout: this.logout,
                    demo: this.plugin.opts.demo,
                    isActiveRow: this.isActiveRow,
                    isChecked: this.isChecked,
                    toggleCheckbox: this.toggleCheckbox,
                    getItemName: this.plugin.getItemName,
                    getItemIcon: this.plugin.getItemIcon,
                    handleScroll: this.handleScroll,
                    done: this.donePicking,
                    title: this.plugin.title,
                    viewType: this.opts.viewType
                });

                return Browser(browserProps);
            };

            return View;
        }();

    },{"../../../core/Utils":77,"./AuthView":105,"./Browser":108,"./Loader":110,"preact":46}],114:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../core/Plugin');

        module.exports = function (_Plugin) {
            _inherits(Redux, _Plugin);

            function Redux(uppy, opts) {
                _classCallCheck(this, Redux);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'state-sync';
                _this.id = 'Redux';
                _this.title = 'Redux Emitter';

                if (typeof opts.action === 'undefined') {
                    throw new Error('action option is not defined');
                }
                if (typeof opts.dispatch === 'undefined') {
                    throw new Error('dispatch option is not defined');
                }
                _this.opts = opts;

                _this.handleStateUpdate = _this.handleStateUpdate.bind(_this);
                return _this;
            }

            Redux.prototype.handleStateUpdate = function handleStateUpdate(prev, state, patch) {
                this.opts.dispatch(this.opts.action(prev, state, patch)); // this dispatches a redux event with the new state
            };

            Redux.prototype.install = function install() {
                this.uppy.on('state-update', this.handleStateUpdate);
                this.handleStateUpdate({}, this.uppy.state, this.uppy.state); // set the initial redux state
            };

            Redux.prototype.uninstall = function uninstall() {
                this.uppy.off('state-update', this.handleStateUpdate);
            };

            return Redux;
        }(Plugin);

    },{"../core/Plugin":74}],115:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../core/Plugin');

        /**
         * Add Redux DevTools support to Uppy
         *
         * See https://medium.com/@zalmoxis/redux-devtools-without-redux-or-how-to-have-a-predictable-state-with-any-architecture-61c5f5a7716f
         * and https://github.com/zalmoxisus/mobx-remotedev/blob/master/src/monitorActions.js
         */
        module.exports = function (_Plugin) {
            _inherits(ReduxDevTools, _Plugin);

            function ReduxDevTools(uppy, opts) {
                _classCallCheck(this, ReduxDevTools);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'debugger';
                _this.id = 'ReduxDevTools';
                _this.title = 'Redux DevTools';

                // set default options
                var defaultOptions = {};

                // merge default options with the ones set by user
                _this.opts = _extends({}, defaultOptions, opts);

                _this.handleStateChange = _this.handleStateChange.bind(_this);
                _this.initDevTools = _this.initDevTools.bind(_this);
                return _this;
            }

            ReduxDevTools.prototype.handleStateChange = function handleStateChange(prevState, nextState, patch) {
                this.devTools.send('UPPY_STATE_UPDATE', nextState);
            };

            ReduxDevTools.prototype.initDevTools = function initDevTools() {
                var _this2 = this;

                this.devTools = window.devToolsExtension.connect();
                this.devToolsUnsubscribe = this.devTools.subscribe(function (message) {
                    if (message.type === 'DISPATCH') {
                        console.log(message.payload.type);

                        // Implement monitors actions
                        switch (message.payload.type) {
                            case 'RESET':
                                _this2.uppy.reset();
                                return;
                            case 'IMPORT_STATE':
                                var computedStates = message.payload.nextLiftedState.computedStates;
                                _this2.uppy.state = _extends({}, _this2.uppy.state, computedStates[computedStates.length - 1].state);
                                _this2.uppy.updateAll(_this2.uppy.state);
                                return;
                            case 'JUMP_TO_STATE':
                            case 'JUMP_TO_ACTION':
                                _this2.uppy.store.state = _extends({}, _this2.uppy.state, JSON.parse(message.state));
                                _this2.uppy.updateAll(_this2.uppy.state);
                        }
                    }
                });
            };

            ReduxDevTools.prototype.install = function install() {
                this.withDevTools = typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__;
                if (this.withDevTools) {
                    this.initDevTools();
                    this.uppy.on('state-update', this.handleStateChange);
                }
            };

            ReduxDevTools.prototype.uninstall = function uninstall() {
                if (this.withDevTools) {
                    this.devToolsUnsubscribe();
                    this.uppy.off('state-update', this.handleStateUpdate);
                }
            };

            return ReduxDevTools;
        }(Plugin);

    },{"../core/Plugin":74}],116:[function(require,module,exports){
        'use strict';

        var throttle = require('lodash.throttle');

        var _require = require('preact'),
            h = _require.h;

        function progressDetails(props) {
            return h(
                'span',
                null,
                props.totalProgress || 0,
                '%\u30FB',
                props.complete,
                ' / ',
                props.inProgress,
                '\u30FB',
                props.totalUploadedSize,
                ' / ',
                props.totalSize,
                '\u30FB\u2191 ',
                props.totalSpeed,
                '/s\u30FB',
                props.totalETA
            );
        }

        var ThrottledProgressDetails = throttle(progressDetails, 500, { leading: true, trailing: true });

        var STATE_ERROR = 'error';
        var STATE_WAITING = 'waiting';
        var STATE_PREPROCESSING = 'preprocessing';
        var STATE_UPLOADING = 'uploading';
        var STATE_POSTPROCESSING = 'postprocessing';
        var STATE_COMPLETE = 'complete';

        function getUploadingState(props, files) {
            if (props.isAllErrored) {
                return STATE_ERROR;
            }

            // If ALL files have been completed, show the completed state.
            if (props.isAllComplete) {
                return STATE_COMPLETE;
            }

            var state = STATE_WAITING;
            var fileIDs = Object.keys(files);
            for (var i = 0; i < fileIDs.length; i++) {
                var progress = files[fileIDs[i]].progress;
                // If ANY files are being uploaded right now, show the uploading state.
                if (progress.uploadStarted && !progress.uploadComplete) {
                    return STATE_UPLOADING;
                }
                // If files are being preprocessed AND postprocessed at this time, we show the
                // preprocess state. If any files are being uploaded we show uploading.
                if (progress.preprocess && state !== STATE_UPLOADING) {
                    state = STATE_PREPROCESSING;
                }
                // If NO files are being preprocessed or uploaded right now, but some files are
                // being postprocessed, show the postprocess state.
                if (progress.postprocess && state !== STATE_UPLOADING && state !== STATE_PREPROCESSING) {
                    state = STATE_POSTPROCESSING;
                }
            }
            return state;
        }

        function calculateProcessingProgress(files) {
            // Collect pre or postprocessing progress states.
            var progresses = [];
            Object.keys(files).forEach(function (fileID) {
                var progress = files[fileID].progress;

                if (progress.preprocess) {
                    progresses.push(progress.preprocess);
                }
                if (progress.postprocess) {
                    progresses.push(progress.postprocess);
                }
            });

            // In the future we should probably do this differently. For now we'll take the
            // mode and message from the first fileâ€¦
            var _progresses$ = progresses[0],
                mode = _progresses$.mode,
                message = _progresses$.message;

            var value = progresses.filter(isDeterminate).reduce(function (total, progress, index, all) {
                return total + progress.value / all.length;
            }, 0);
            function isDeterminate(progress) {
                return progress.mode === 'determinate';
            }

            return {
                mode: mode,
                message: message,
                value: value
            };
        }

        function togglePauseResume(props) {
            if (props.isAllComplete) return;

            if (!props.resumableUploads) {
                return props.cancelAll();
            }

            if (props.isAllPaused) {
                return props.resumeAll();
            }

            return props.pauseAll();
        }

        module.exports = function (props) {
            props = props || {};

            var uploadState = getUploadingState(props, props.files || {});

            var progressValue = props.totalProgress;
            var progressMode = void 0;
            var progressBarContent = void 0;
            if (uploadState === STATE_PREPROCESSING || uploadState === STATE_POSTPROCESSING) {
                var progress = calculateProcessingProgress(props.files);
                progressMode = progress.mode;
                if (progressMode === 'determinate') {
                    progressValue = progress.value * 100;
                }

                progressBarContent = ProgressBarProcessing(progress);
            } else if (uploadState === STATE_COMPLETE) {
                progressBarContent = ProgressBarComplete(props);
            } else if (uploadState === STATE_UPLOADING) {
                progressBarContent = ProgressBarUploading(props);
            } else if (uploadState === STATE_ERROR) {
                progressValue = undefined;
                progressBarContent = ProgressBarError(props);
            }

            var width = typeof progressValue === 'number' ? progressValue : 100;
            var isHidden = uploadState === STATE_WAITING && props.hideUploadButton || uploadState === STATE_WAITING && !props.newFiles > 0 || uploadState === STATE_COMPLETE && props.hideAfterFinish;

            var progressClasses = 'uppy-StatusBar-progress\n                           ' + (progressMode ? 'is-' + progressMode : '');

            return h(
                'div',
                { 'class': 'uppy uppy-StatusBar is-' + uploadState, 'aria-hidden': isHidden },
                h('div', { 'class': progressClasses,
                    style: { width: width + '%' },
                    role: 'progressbar',
                    'aria-valuemin': '0',
                    'aria-valuemax': '100',
                    'aria-valuenow': progressValue }),
                progressBarContent,
                h(
                    'div',
                    { 'class': 'uppy-StatusBar-actions' },
                    props.newFiles && !props.hideUploadButton ? h(UploadBtn, props) : null,
                    props.error ? h(RetryBtn, props) : null
                )
            );
        };

        var UploadBtn = function UploadBtn(props) {
            return h(
                'button',
                { type: 'button',
                    'class': 'uppy-StatusBar-actionBtn uppy-StatusBar-actionBtn--upload',
                    'aria-label': props.i18n('uploadXFiles', { smart_count: props.newFiles }),
                    onclick: props.startUpload },
                props.inProgress ? props.i18n('uploadXNewFiles', { smart_count: props.newFiles }) : props.i18n('uploadXFiles', { smart_count: props.newFiles })
            );
        };

        var RetryBtn = function RetryBtn(props) {
            return h(
                'button',
                { type: 'button',
                    'class': 'uppy-StatusBar-actionBtn uppy-StatusBar-actionBtn--retry',
                    'aria-label': props.i18n('retryUpload'),
                    onclick: props.retryAll },
                props.i18n('retry')
            );
        };

        var ProgressBarProcessing = function ProgressBarProcessing(props) {
            var value = Math.round(props.value * 100);

            return h(
                'div',
                { 'class': 'uppy-StatusBar-content' },
                props.mode === 'determinate' ? value + '%\u30FB' : '',
                props.message
            );
        };

        var ProgressBarUploading = function ProgressBarUploading(props) {
            return h(
                'div',
                { 'class': 'uppy-StatusBar-content' },
                props.isUploadStarted && !props.isAllComplete ? !props.isAllPaused ? h(
                    'div',
                    { title: 'Uploading' },
                    h(PauseResumeButtons, props),
                    ' Uploading... ',
                    h(ThrottledProgressDetails, props)
                ) : h(
                    'div',
                    { title: 'Paused' },
                    h(PauseResumeButtons, props),
                    ' Paused\u30FB',
                    props.totalProgress,
                    '%'
                ) : null
            );
        };

        var ProgressBarComplete = function ProgressBarComplete(_ref) {
            var totalProgress = _ref.totalProgress,
                i18n = _ref.i18n;

            return h(
                'div',
                { 'class': 'uppy-StatusBar-content', role: 'status' },
                h(
                    'span',
                    { title: 'Complete' },
                    h(
                        'svg',
                        { 'aria-hidden': 'true', 'class': 'uppy-StatusBar-statusIndicator UppyIcon', width: '18', height: '17', viewBox: '0 0 23 17' },
                        h('path', { d: 'M8.944 17L0 7.865l2.555-2.61 6.39 6.525L20.41 0 23 2.645z' })
                    ),
                    i18n('uploadComplete'),
                    '\u30FB',
                    totalProgress,
                    '%'
                )
            );
        };

        var ProgressBarError = function ProgressBarError(_ref2) {
            var error = _ref2.error,
                retryAll = _ref2.retryAll,
                i18n = _ref2.i18n;

            return h(
                'div',
                { 'class': 'uppy-StatusBar-content', role: 'alert' },
                h(
                    'strong',
                    null,
                    i18n('uploadFailed'),
                    '.'
                ),
                ' ',
                h(
                    'span',
                    null,
                    i18n('pleasePressRetry')
                ),
                h(
                    'span',
                    { 'class': 'uppy-StatusBar-details',
                        'aria-label': error,
                        'data-microtip-position': 'top',
                        'data-microtip-size': 'large',
                        role: 'tooltip' },
                    '?'
                )
            );
        };

        var PauseResumeButtons = function PauseResumeButtons(props) {
            var resumableUploads = props.resumableUploads,
                isAllPaused = props.isAllPaused,
                i18n = props.i18n;

            var title = resumableUploads ? isAllPaused ? i18n('resumeUpload') : i18n('pauseUpload') : i18n('cancelUpload');

            return h(
                'button',
                { title: title, 'class': 'uppy-StatusBar-statusIndicator', type: 'button', onclick: function onclick() {
                        return togglePauseResume(props);
                    } },
                resumableUploads ? isAllPaused ? h(
                    'svg',
                    { 'aria-hidden': 'true', 'class': 'UppyIcon', width: '15', height: '17', viewBox: '0 0 11 13' },
                    h('path', { d: 'M1.26 12.534a.67.67 0 0 1-.674.012.67.67 0 0 1-.336-.583v-11C.25.724.38.5.586.382a.658.658 0 0 1 .673.012l9.165 5.5a.66.66 0 0 1 .325.57.66.66 0 0 1-.325.573l-9.166 5.5z' })
                ) : h(
                    'svg',
                    { 'aria-hidden': 'true', 'class': 'UppyIcon', width: '16', height: '17', viewBox: '0 0 12 13' },
                    h('path', { d: 'M4.888.81v11.38c0 .446-.324.81-.722.81H2.722C2.324 13 2 12.636 2 12.19V.81c0-.446.324-.81.722-.81h1.444c.398 0 .722.364.722.81zM9.888.81v11.38c0 .446-.324.81-.722.81H7.722C7.324 13 7 12.636 7 12.19V.81c0-.446.324-.81.722-.81h1.444c.398 0 .722.364.722.81z' })
                ) : h(
                    'svg',
                    { 'aria-hidden': 'true', 'class': 'UppyIcon', width: '16px', height: '16px', viewBox: '0 0 19 19' },
                    h('path', { d: 'M17.318 17.232L9.94 9.854 9.586 9.5l-.354.354-7.378 7.378h.707l-.62-.62v.706L9.318 9.94l.354-.354-.354-.354L1.94 1.854v.707l.62-.62h-.706l7.378 7.378.354.354.354-.354 7.378-7.378h-.707l.622.62v-.706L9.854 9.232l-.354.354.354.354 7.378 7.378.708-.707-7.38-7.378v.708l7.38-7.38.353-.353-.353-.353-.622-.622-.353-.353-.354.352-7.378 7.38h.708L2.56 1.23 2.208.88l-.353.353-.622.62-.353.355.352.353 7.38 7.38v-.708l-7.38 7.38-.353.353.352.353.622.622.353.353.354-.353 7.38-7.38h-.708l7.38 7.38z' })
                )
            );
        };

    },{"lodash.throttle":40,"preact":46}],117:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var Plugin = require('../../core/Plugin');
        var Translator = require('../../core/Translator');
        var StatusBarUI = require('./StatusBar');

        var _require = require('../../core/Utils'),
            getSpeed = _require.getSpeed;

        var _require2 = require('../../core/Utils'),
            getBytesRemaining = _require2.getBytesRemaining;

        var _require3 = require('../../core/Utils'),
            prettyETA = _require3.prettyETA;

        var prettyBytes = require('prettier-bytes');

        /**
         * A status bar.
         */
        module.exports = function (_Plugin) {
            _inherits(StatusBar, _Plugin);

            function StatusBar(uppy, opts) {
                _classCallCheck(this, StatusBar);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.id = _this.opts.id || 'StatusBar';
                _this.title = 'StatusBar';
                _this.type = 'progressindicator';

                var defaultLocale = {
                    strings: {
                        uploading: 'Uploading',
                        uploadComplete: 'Upload complete',
                        uploadFailed: 'Upload failed',
                        pleasePressRetry: 'Please press Retry to upload again',
                        paused: 'Paused',
                        error: 'Error',
                        retry: 'Retry',
                        pressToRetry: 'Press to retry',
                        retryUpload: 'Retry upload',
                        resumeUpload: 'Resume upload',
                        cancelUpload: 'Cancel upload',
                        pauseUpload: 'Pause upload',
                        uploadXFiles: {
                            0: 'Upload %{smart_count} file',
                            1: 'Upload %{smart_count} files'
                        },
                        uploadXNewFiles: {
                            0: 'Upload +%{smart_count} file',
                            1: 'Upload +%{smart_count} files'
                        }
                    }

                    // set default options
                };var defaultOptions = {
                    target: 'body',
                    hideUploadButton: false,
                    showProgressDetails: false,
                    locale: defaultLocale,
                    hideAfterFinish: true

                    // merge default options with the ones set by user
                };_this.opts = _extends({}, defaultOptions, opts);

                _this.locale = _extends({}, defaultLocale, _this.opts.locale);
                _this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);

                _this.translator = new Translator({ locale: _this.locale });
                _this.i18n = _this.translator.translate.bind(_this.translator);

                _this.startUpload = _this.startUpload.bind(_this);
                _this.render = _this.render.bind(_this);
                _this.install = _this.install.bind(_this);
                return _this;
            }

            StatusBar.prototype.getTotalSpeed = function getTotalSpeed(files) {
                var totalSpeed = 0;
                files.forEach(function (file) {
                    totalSpeed = totalSpeed + getSpeed(file.progress);
                });
                return totalSpeed;
            };

            StatusBar.prototype.getTotalETA = function getTotalETA(files) {
                var totalSpeed = this.getTotalSpeed(files);
                if (totalSpeed === 0) {
                    return 0;
                }

                var totalBytesRemaining = files.reduce(function (total, file) {
                    return total + getBytesRemaining(file.progress);
                }, 0);

                return Math.round(totalBytesRemaining / totalSpeed * 10) / 10;
            };

            StatusBar.prototype.startUpload = function startUpload() {
                return this.uppy.upload().catch(function () {
                    // Ignore
                });
            };

            StatusBar.prototype.render = function render(state) {
                var files = state.files;

                var uploadStartedFiles = Object.keys(files).filter(function (file) {
                    return files[file].progress.uploadStarted;
                });
                var newFiles = Object.keys(files).filter(function (file) {
                    return !files[file].progress.uploadStarted && !files[file].progress.preprocess && !files[file].progress.postprocess;
                });
                var completeFiles = Object.keys(files).filter(function (file) {
                    return files[file].progress.uploadComplete;
                });
                var erroredFiles = Object.keys(files).filter(function (file) {
                    return files[file].error;
                });
                var inProgressFiles = Object.keys(files).filter(function (file) {
                    return !files[file].progress.uploadComplete && files[file].progress.uploadStarted && !files[file].isPaused;
                });
                var processingFiles = Object.keys(files).filter(function (file) {
                    return files[file].progress.preprocess || files[file].progress.postprocess;
                });

                var inProgressFilesArray = [];
                inProgressFiles.forEach(function (file) {
                    inProgressFilesArray.push(files[file]);
                });

                var totalSpeed = prettyBytes(this.getTotalSpeed(inProgressFilesArray));
                var totalETA = prettyETA(this.getTotalETA(inProgressFilesArray));

                // total size and uploaded size
                var totalSize = 0;
                var totalUploadedSize = 0;
                inProgressFilesArray.forEach(function (file) {
                    totalSize = totalSize + (file.progress.bytesTotal || 0);
                    totalUploadedSize = totalUploadedSize + (file.progress.bytesUploaded || 0);
                });
                totalSize = prettyBytes(totalSize);
                totalUploadedSize = prettyBytes(totalUploadedSize);

                var isUploadStarted = uploadStartedFiles.length > 0;

                var isAllComplete = state.totalProgress === 100 && completeFiles.length === Object.keys(files).length && processingFiles.length === 0;

                var isAllErrored = isUploadStarted && erroredFiles.length === uploadStartedFiles.length;

                var isAllPaused = inProgressFiles.length === 0 && !isAllComplete && !isAllErrored && uploadStartedFiles.length > 0;

                var resumableUploads = this.uppy.getState().capabilities.resumableUploads || false;

                return StatusBarUI({
                    error: state.error,
                    totalProgress: state.totalProgress,
                    totalSize: totalSize,
                    totalUploadedSize: totalUploadedSize,
                    uploadStartedFiles: uploadStartedFiles,
                    isAllComplete: isAllComplete,
                    isAllPaused: isAllPaused,
                    isAllErrored: isAllErrored,
                    isUploadStarted: isUploadStarted,
                    i18n: this.i18n,
                    pauseAll: this.uppy.pauseAll,
                    resumeAll: this.uppy.resumeAll,
                    retryAll: this.uppy.retryAll,
                    cancelAll: this.uppy.cancelAll,
                    startUpload: this.startUpload,
                    complete: completeFiles.length,
                    newFiles: newFiles.length,
                    inProgress: uploadStartedFiles.length,
                    totalSpeed: totalSpeed,
                    totalETA: totalETA,
                    files: state.files,
                    resumableUploads: resumableUploads,
                    hideUploadButton: this.opts.hideUploadButton,
                    hideAfterFinish: this.opts.hideAfterFinish
                });
            };

            StatusBar.prototype.install = function install() {
                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }
            };

            StatusBar.prototype.uninstall = function uninstall() {
                this.unmount();
            };

            return StatusBar;
        }(Plugin);

    },{"../../core/Plugin":74,"../../core/Translator":75,"../../core/Utils":77,"./StatusBar":116,"prettier-bytes":47}],118:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var Plugin = require('../../core/Plugin');
        var Utils = require('../../core/Utils');
        /**
         * The Thumbnail Generator plugin
         *
         */

        module.exports = function (_Plugin) {
            _inherits(ThumbnailGenerator, _Plugin);

            function ThumbnailGenerator(uppy, opts) {
                _classCallCheck(this, ThumbnailGenerator);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'thumbnail';
                _this.id = 'ThumbnailGenerator';
                _this.title = 'Thumbnail Generator';
                _this.queue = [];
                _this.queueProcessing = false;

                var defaultOptions = {
                    thumbnailWidth: 200
                };

                _this.opts = _extends({}, defaultOptions, opts);

                _this.addToQueue = _this.addToQueue.bind(_this);
                return _this;
            }

            /**
             * Create a thumbnail for the given Uppy file object.
             *
             * @param {{data: Blob}} file
             * @param {number} width
             * @return {Promise}
             */


            ThumbnailGenerator.prototype.createThumbnail = function createThumbnail(file, targetWidth) {
                var _this2 = this;

                var originalUrl = URL.createObjectURL(file.data);
                var onload = new _Promise(function (resolve, reject) {
                    var image = new Image();
                    image.src = originalUrl;
                    image.onload = function () {
                        URL.revokeObjectURL(originalUrl);
                        resolve(image);
                    };
                    image.onerror = function () {
                        // The onerror event is totally useless unfortunately, as far as I know
                        URL.revokeObjectURL(originalUrl);
                        reject(new Error('Could not create thumbnail'));
                    };
                });

                return onload.then(function (image) {
                    var targetHeight = _this2.getProportionalHeight(image, targetWidth);
                    var canvas = _this2.resizeImage(image, targetWidth, targetHeight);
                    return _this2.canvasToBlob(canvas, 'image/png');
                }).then(function (blob) {
                    return URL.createObjectURL(blob);
                });
            };

            /**
             * Make sure the image doesnâ€™t exceed browser/device canvas limits.
             * For ios with 256 RAM and ie
             */


            ThumbnailGenerator.prototype.protect = function protect(image) {
                // https://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-element

                var ratio = image.width / image.height;

                var maxSquare = 5000000; // ios max canvas square
                var maxSize = 4096; // ie max canvas dimensions

                var maxW = Math.floor(Math.sqrt(maxSquare * ratio));
                var maxH = Math.floor(maxSquare / Math.sqrt(maxSquare * ratio));
                if (maxW > maxSize) {
                    maxW = maxSize;
                    maxH = Math.round(maxW / ratio);
                }
                if (maxH > maxSize) {
                    maxH = maxSize;
                    maxW = Math.round(ratio * maxH);
                }
                if (image.width > maxW) {
                    var canvas = document.createElement('canvas');
                    canvas.width = maxW;
                    canvas.height = maxH;
                    canvas.getContext('2d').drawImage(image, 0, 0, maxW, maxH);
                    image.src = 'about:blank';
                    image.width = 1;
                    image.height = 1;
                    image = canvas;
                }

                return image;
            };

            /**
             * Resize an image to the target `width` and `height`.
             *
             * Returns a Canvas with the resized image on it.
             */


            ThumbnailGenerator.prototype.resizeImage = function resizeImage(image, targetWidth, targetHeight) {
                // Resizing in steps refactored to use a solution from
                // https://blog.uploadcare.com/image-resize-in-browsers-is-broken-e38eed08df01

                image = this.protect(image);

                var steps = Math.ceil(Math.log2(image.width / targetWidth));
                var sW = targetWidth * Math.pow(2, steps - 1);
                var sH = targetHeight * Math.pow(2, steps - 1);
                var x = 2;

                if(steps < 1) steps = 1;

                while (steps--) {
                    var canvas = document.createElement('canvas');
                    canvas.width = sW;
                    canvas.height = sH;
                    canvas.getContext('2d').drawImage(image, 0, 0, sW, sH);
                    image = canvas;

                    sW = Math.round(sW / x);
                    sH = Math.round(sH / x);
                }

                return image;
            };

            /**
             * Save a <canvas> element's content to a Blob object.
             *
             * @param {HTMLCanvasElement} canvas
             * @return {Promise}
             */


            ThumbnailGenerator.prototype.canvasToBlob = function canvasToBlob(canvas, type, quality) {
                if (canvas.toBlob) {
                    return new _Promise(function (resolve) {
                        canvas.toBlob(resolve, type, quality);
                    });
                }
                return _Promise.resolve().then(function () {
                    return Utils.dataURItoBlob(canvas.toDataURL(type, quality), {});
                });
            };

            ThumbnailGenerator.prototype.getProportionalHeight = function getProportionalHeight(img, width) {
                var aspect = img.width / img.height;
                return Math.round(width / aspect);
            };

            /**
             * Set the preview URL for a file.
             */


            ThumbnailGenerator.prototype.setPreviewURL = function setPreviewURL(fileID, preview) {
                var _extends2;

                var files = this.uppy.state.files;

                this.uppy.setState({
                    files: _extends({}, files, (_extends2 = {}, _extends2[fileID] = _extends({}, files[fileID], {
                        preview: preview
                    }), _extends2))
                });
            };

            ThumbnailGenerator.prototype.addToQueue = function addToQueue(item) {
                this.queue.push(item);
                if (this.queueProcessing === false) {
                    this.processQueue();
                }
            };

            ThumbnailGenerator.prototype.processQueue = function processQueue() {
                var _this3 = this;

                this.queueProcessing = true;
                if (this.queue.length > 0) {
                    var current = this.queue.shift();
                    return this.requestThumbnail(current).catch(function (err) {}) // eslint-disable-line handle-callback-err
                        .then(function () {
                            return _this3.processQueue();
                        });
                } else {
                    this.queueProcessing = false;
                }
            };

            ThumbnailGenerator.prototype.requestThumbnail = function requestThumbnail(file) {
                var _this4 = this;

                if (Utils.isPreviewSupported(file.type) && !file.isRemote) {
                    return this.createThumbnail(file, this.opts.thumbnailWidth).then(function (preview) {
                        _this4.setPreviewURL(file.id, preview);
                    }).catch(function (err) {
                        console.warn(err.stack || err.message);
                    });
                }
                return _Promise.resolve();
            };

            ThumbnailGenerator.prototype.install = function install() {
                this.uppy.on('file-added', this.addToQueue);
            };

            ThumbnailGenerator.prototype.uninstall = function uninstall() {
                this.uppy.off('file-added', this.addToQueue);
            };

            return ThumbnailGenerator;
        }(Plugin);

    },{"../../core/Plugin":74,"../../core/Utils":77,"es6-promise":33}],119:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        /**
         * A Barebones HTTP API client for Transloadit.
         */
        module.exports = function () {
            function Client() {
                var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

                _classCallCheck(this, Client);

                this.apiUrl = 'https://api2.transloadit.com';
                this.opts = opts;
            }

            /**
             * Create a new assembly.
             *
             * @param {object} options
             */


            Client.prototype.createAssembly = function createAssembly(_ref) {
                var templateId = _ref.templateId,
                    params = _ref.params,
                    fields = _ref.fields,
                    signature = _ref.signature,
                    expectedFiles = _ref.expectedFiles;

                var data = new FormData();
                data.append('params', typeof params === 'string' ? params : JSON.stringify(params));
                if (signature) {
                    data.append('signature', signature);
                }

                Object.keys(fields).forEach(function (key) {
                    data.append(key, fields[key]);
                });
                data.append('num_expected_upload_files', expectedFiles);

                return fetch(this.apiUrl + '/assemblies', {
                    method: 'post',
                    body: data
                }).then(function (response) {
                    return response.json();
                }).then(function (assembly) {
                    if (assembly.error) {
                        var error = new Error(assembly.message);
                        error.code = assembly.error;
                        error.status = assembly;
                        throw error;
                    }

                    return assembly;
                });
            };

            Client.prototype.reserveFile = function reserveFile(assembly, file) {
                var size = encodeURIComponent(file.size);
                return fetch(assembly.assembly_ssl_url + '/reserve_file?size=' + size, { method: 'post' }).then(function (response) {
                    return response.json();
                });
            };

            Client.prototype.addFile = function addFile(assembly, file) {
                if (!file.uploadURL) {
                    return _Promise.reject(new Error('File does not have an `uploadURL`.'));
                }
                var size = encodeURIComponent(file.size);
                var url = encodeURIComponent(file.uploadURL);
                var filename = encodeURIComponent(file.name);
                var fieldname = 'file';

                var qs = 'size=' + size + '&filename=' + filename + '&fieldname=' + fieldname + '&s3Url=' + url;
                return fetch(assembly.assembly_ssl_url + '/add_file?' + qs, { method: 'post' }).then(function (response) {
                    return response.json();
                });
            };

            /**
             * Get the current status for an assembly.
             *
             * @param {string} url The status endpoint of the assembly.
             */


            Client.prototype.getAssemblyStatus = function getAssemblyStatus(url) {
                return fetch(url).then(function (response) {
                    return response.json();
                });
            };

            return Client;
        }();

    },{"es6-promise":33}],120:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        var io = require('socket.io-client');
        var Emitter = require('namespace-emitter');
        var parseUrl = require('url-parse');

        /**
         * WebSocket status API client for Transloadit.
         */
        module.exports = function () {
            function TransloaditSocket(url, assembly) {
                _classCallCheck(this, TransloaditSocket);

                var emitter = Emitter();
                this.on = emitter.on.bind(emitter);
                this.off = emitter.off.bind(emitter);
                this.emit = emitter.emit.bind(emitter);

                var parsed = parseUrl(url);

                this.assembly = assembly;
                this.socket = io.connect(parsed.origin, {
                    path: parsed.pathname
                });

                this.attachDefaultHandlers();
            }

            TransloaditSocket.prototype.attachDefaultHandlers = function attachDefaultHandlers() {
                var _this = this;

                this.socket.on('connect', function () {
                    _this.socket.emit('assembly_connect', {
                        id: _this.assembly.assembly_id
                    });

                    _this.emit('connect');
                });

                this.socket.on('assembly_finished', function () {
                    _this.emit('finished');

                    _this.close();
                });

                this.socket.on('assembly_upload_finished', function (file) {
                    _this.emit('upload', file);
                });

                this.socket.on('assembly_uploading_finished', function () {
                    _this.emit('executing');
                });

                this.socket.on('assembly_upload_meta_data_extracted', function () {
                    _this.emit('metadata');
                });

                this.socket.on('assembly_result_finished', function (stepName, result) {
                    _this.emit('result', stepName, result);
                });

                this.socket.on('assembly_error', function (err) {
                    _this.emit('error', _extends(new Error(err.message), err));
                });
            };

            TransloaditSocket.prototype.close = function close() {
                this.socket.disconnect();
            };

            return TransloaditSocket;
        }();

    },{"namespace-emitter":43,"socket.io-client":52,"url-parse":69}],121:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var Translator = require('../../core/Translator');
        var Plugin = require('../../core/Plugin');
        var Client = require('./Client');
        var StatusSocket = require('./Socket');

        function defaultGetAssemblyOptions(file, options) {
            return {
                params: options.params,
                signature: options.signature,
                fields: options.fields
            };
        }

        /**
         * Upload files to Transloadit using Tus.
         */
        module.exports = function (_Plugin) {
            _inherits(Transloadit, _Plugin);

            function Transloadit(uppy, opts) {
                _classCallCheck(this, Transloadit);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'uploader';
                _this.id = 'Transloadit';
                _this.title = 'Transloadit';

                var defaultLocale = {
                    strings: {
                        creatingAssembly: 'Preparing upload...',
                        creatingAssemblyFailed: 'Transloadit: Could not create assembly',
                        encoding: 'Encoding...'
                    }
                };

                var defaultOptions = {
                    waitForEncoding: false,
                    waitForMetadata: false,
                    alwaysRunAssembly: false,
                    importFromUploadURLs: false,
                    signature: null,
                    params: null,
                    fields: {},
                    getAssemblyOptions: defaultGetAssemblyOptions,
                    locale: defaultLocale
                };

                _this.opts = _extends({}, defaultOptions, opts);

                _this.locale = _extends({}, defaultLocale, _this.opts.locale);
                _this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);

                _this.translator = new Translator({ locale: _this.locale });
                _this.i18n = _this.translator.translate.bind(_this.translator);

                _this.prepareUpload = _this.prepareUpload.bind(_this);
                _this.afterUpload = _this.afterUpload.bind(_this);
                _this.onFileUploadURLAvailable = _this.onFileUploadURLAvailable.bind(_this);
                _this.onRestored = _this.onRestored.bind(_this);
                _this.getPersistentData = _this.getPersistentData.bind(_this);

                if (_this.opts.params) {
                    _this.validateParams(_this.opts.params);
                }

                _this.client = new Client();
                _this.sockets = {};
                return _this;
            }

            Transloadit.prototype.validateParams = function validateParams(params) {
                if (!params) {
                    throw new Error('Transloadit: The `params` option is required.');
                }

                if (typeof params === 'string') {
                    try {
                        params = JSON.parse(params);
                    } catch (err) {
                        // Tell the user that this is not an Uppy bug!
                        err.message = 'Transloadit: The `params` option is a malformed JSON string: ' + err.message;
                        throw err;
                    }
                }

                if (!params.auth || !params.auth.key) {
                    throw new Error('Transloadit: The `params.auth.key` option is required. ' + 'You can find your Transloadit API key at https://transloadit.com/accounts/credentials.');
                }
            };

            Transloadit.prototype.getAssemblyOptions = function getAssemblyOptions(fileIDs) {
                var _this2 = this;

                var options = this.opts;

                var normalizeAssemblyOptions = function normalizeAssemblyOptions(file, assemblyOptions) {
                    if (Array.isArray(assemblyOptions.fields)) {
                        var fieldNames = assemblyOptions.fields;
                        assemblyOptions.fields = {};
                        fieldNames.forEach(function (fieldName) {
                            assemblyOptions.fields[fieldName] = file.meta[fieldName];
                        });
                    }
                    if (!assemblyOptions.fields) {
                        assemblyOptions.fields = {};
                    }
                    return assemblyOptions;
                };

                return _Promise.all(fileIDs.map(function (fileID) {
                    var file = _this2.uppy.getFile(fileID);
                    var promise = _Promise.resolve().then(function () {
                        return options.getAssemblyOptions(file, options);
                    }).then(function (assemblyOptions) {
                        return normalizeAssemblyOptions(file, assemblyOptions);
                    });
                    return promise.then(function (assemblyOptions) {
                        _this2.validateParams(assemblyOptions.params);

                        return {
                            fileIDs: [fileID],
                            options: assemblyOptions
                        };
                    });
                }));
            };

            Transloadit.prototype.dedupeAssemblyOptions = function dedupeAssemblyOptions(list) {
                var dedupeMap = Object.create(null);
                list.forEach(function (_ref) {
                    var fileIDs = _ref.fileIDs,
                        options = _ref.options;

                    var id = JSON.stringify(options);
                    if (dedupeMap[id]) {
                        var _dedupeMap$id$fileIDs;

                        (_dedupeMap$id$fileIDs = dedupeMap[id].fileIDs).push.apply(_dedupeMap$id$fileIDs, fileIDs);
                    } else {
                        dedupeMap[id] = {
                            options: options,
                            fileIDs: [].concat(fileIDs)
                        };
                    }
                });

                return Object.keys(dedupeMap).map(function (id) {
                    return dedupeMap[id];
                });
            };

            Transloadit.prototype.createAssembly = function createAssembly(fileIDs, uploadID, options) {
                var _this3 = this;

                var pluginOptions = this.opts;

                this.uppy.log('[Transloadit] create assembly');

                return this.client.createAssembly({
                    params: options.params,
                    fields: options.fields,
                    expectedFiles: fileIDs.length,
                    signature: options.signature
                }).then(function (assembly) {
                    var _extends2, _extends3;

                    // Store the list of assemblies related to this upload.
                    var state = _this3.getPluginState();
                    var assemblyList = state.uploadsAssemblies[uploadID];
                    var uploadsAssemblies = _extends({}, state.uploadsAssemblies, (_extends2 = {}, _extends2[uploadID] = assemblyList.concat([assembly.assembly_id]), _extends2));

                    _this3.setPluginState({
                        assemblies: _extends(state.assemblies, (_extends3 = {}, _extends3[assembly.assembly_id] = assembly, _extends3)),
                        uploadsAssemblies: uploadsAssemblies
                    });

                    function attachAssemblyMetadata(file, assembly) {
                        // Attach meta parameters for the Tus plugin. See:
                        // https://github.com/tus/tusd/wiki/Uploading-to-Transloadit-using-tus#uploading-using-tus
                        // TODO Should this `meta` be moved to a `tus.meta` property instead?
                        var tlMeta = {
                            assembly_url: assembly.assembly_url,
                            filename: file.name,
                            fieldname: 'file'
                        };
                        var meta = _extends({}, file.meta, tlMeta);
                        // Add assembly-specific Tus endpoint.
                        var tus = _extends({}, file.tus, {
                            endpoint: assembly.tus_url,
                            // Only send assembly metadata to the tus endpoint.
                            metaFields: Object.keys(tlMeta),
                            // Make sure tus doesn't resume a previous upload.
                            uploadUrl: null,
                            // Disable tus-js-client fingerprinting, otherwise uploading the same file at different times
                            // will upload to the same assembly.
                            resume: false
                        });

                        // Set uppy server location.
                        // we only add this, if 'file' has the attribute remote, because
                        // this is the criteria to identify remote files. If we add it without
                        // the check, then the file automatically becomes a remote file.
                        // @TODO: this is quite hacky. Please fix this later
                        var remote = void 0;
                        if (file.remote) {
                            var newHost = assembly.uppyserver_url;
                            // remove tailing slash
                            if (newHost.endsWith('/')) {
                                newHost = newHost.slice(0, -1);
                            }
                            var path = file.remote.url.replace(file.remote.host, '');
                            // remove leading slash
                            if (path.startsWith('/')) {
                                path = path.slice(1);
                            }
                            remote = _extends({}, file.remote, {
                                host: newHost,
                                url: newHost + '/' + path
                            });
                        }

                        var transloadit = {
                            assembly: assembly.assembly_id
                        };

                        var newFile = _extends({}, file, { transloadit: transloadit });
                        // Only configure the Tus plugin if we are uploading straight to Transloadit (the default).
                        if (!pluginOptions.importFromUploadURLs) {
                            _extends(newFile, { meta: meta, tus: tus, remote: remote });
                        }
                        return newFile;
                    }

                    var files = _extends({}, _this3.uppy.state.files);
                    fileIDs.forEach(function (id) {
                        files[id] = attachAssemblyMetadata(files[id], assembly);
                    });

                    _this3.uppy.setState({ files: files });

                    _this3.uppy.emit('transloadit:assembly-created', assembly, fileIDs);

                    return _this3.connectSocket(assembly).then(function () {
                        return assembly;
                    });
                }).then(function (assembly) {
                    _this3.uppy.log('[Transloadit] Created assembly');
                    return assembly;
                }).catch(function (err) {
                    _this3.uppy.info(_this3.i18n('creatingAssemblyFailed'), 'error', 0);

                    // Reject the promise.
                    throw err;
                });
            };

            Transloadit.prototype.shouldWait = function shouldWait() {
                return this.opts.waitForEncoding || this.opts.waitForMetadata;
            };

            /**
             * Used when `importFromUploadURLs` is enabled: reserves all files in
             * the assembly.
             */


            Transloadit.prototype.reserveFiles = function reserveFiles(assembly, fileIDs) {
                var _this4 = this;

                return _Promise.all(fileIDs.map(function (fileID) {
                    var file = _this4.uppy.getFile(fileID);
                    return _this4.client.reserveFile(assembly, file);
                }));
            };

            /**
             * Used when `importFromUploadURLs` is enabled: adds files to the assembly
             * once they have been fully uploaded.
             */


            Transloadit.prototype.onFileUploadURLAvailable = function onFileUploadURLAvailable(fileID) {
                var _this5 = this;

                var file = this.uppy.getFile(fileID);
                if (!file || !file.transloadit || !file.transloadit.assembly) {
                    return;
                }

                var state = this.getPluginState();
                var assembly = state.assemblies[file.transloadit.assembly];

                this.client.addFile(assembly, file).catch(function (err) {
                    _this5.uppy.log(err);
                    _this5.uppy.emit('transloadit:import-error', assembly, file.id, err);
                });
            };

            Transloadit.prototype.findFile = function findFile(uploadedFile) {
                var files = this.uppy.state.files;
                for (var id in files) {
                    if (!files.hasOwnProperty(id)) {
                        continue;
                    }
                    // Completed file upload.
                    if (files[id].uploadURL === uploadedFile.tus_upload_url) {
                        return files[id];
                    }
                    // In-progress file upload.
                    if (files[id].tus && files[id].tus.uploadUrl === uploadedFile.tus_upload_url) {
                        return files[id];
                    }
                    if (!uploadedFile.is_tus_file) {
                        // Fingers-crossed check for non-tus uploads, eg imported from S3.
                        if (files[id].name === uploadedFile.name && files[id].size === uploadedFile.size) {
                            return files[id];
                        }
                    }
                }
            };

            Transloadit.prototype.onFileUploadComplete = function onFileUploadComplete(assemblyId, uploadedFile) {
                var _extends4;

                var state = this.getPluginState();
                var file = this.findFile(uploadedFile);
                this.setPluginState({
                    files: _extends({}, state.files, (_extends4 = {}, _extends4[uploadedFile.id] = {
                        assembly: assemblyId,
                        id: file.id,
                        uploadedFile: uploadedFile
                    }, _extends4))
                });
                this.uppy.emit('transloadit:upload', uploadedFile, this.getAssembly(assemblyId));
            };

            Transloadit.prototype.onResult = function onResult(assemblyId, stepName, result) {
                var state = this.getPluginState();
                var file = state.files[result.original_id];
                // The `file` may not exist if an import robot was used instead of a file upload.
                result.localId = file ? file.id : null;

                var entry = {
                    result: result,
                    stepName: stepName,
                    id: result.id,
                    assembly: assemblyId
                };

                this.setPluginState({
                    results: [].concat(state.results, [entry])
                });
                this.uppy.emit('transloadit:result', stepName, result, this.getAssembly(assemblyId));
            };

            Transloadit.prototype.onAssemblyFinished = function onAssemblyFinished(url) {
                var _this6 = this;

                this.client.getAssemblyStatus(url).then(function (assembly) {
                    var _extends5;

                    var state = _this6.getPluginState();
                    _this6.setPluginState({
                        assemblies: _extends({}, state.assemblies, (_extends5 = {}, _extends5[assembly.assembly_id] = assembly, _extends5))
                    });
                    _this6.uppy.emit('transloadit:complete', assembly);
                });
            };

            Transloadit.prototype.getPersistentData = function getPersistentData(setData) {
                var _setData;

                var state = this.getPluginState();
                var assemblies = state.assemblies;
                var uploadsAssemblies = state.uploadsAssemblies;
                var uploads = Object.keys(state.files);
                var results = state.results.map(function (result) {
                    return result.id;
                });

                setData((_setData = {}, _setData[this.id] = {
                    assemblies: assemblies,
                    uploadsAssemblies: uploadsAssemblies,
                    uploads: uploads,
                    results: results
                }, _setData));
            };

            /**
             * Emit the necessary events that must have occured to get from the `prevState`,
             * to the current state.
             * For completed uploads, `transloadit:upload` is emitted.
             * For new results, `transloadit:result` is emitted.
             * For completed or errored assemblies, `transloadit:complete` or `transloadit:assembly-error` is emitted.
             */


            Transloadit.prototype.emitEventsDiff = function emitEventsDiff(prevState) {
                var _this7 = this;

                var opts = this.opts;
                var state = this.getPluginState();

                var emitMissedEvents = function emitMissedEvents() {
                    // Emit events for completed uploads and completed results
                    // that we've missed while we were away.
                    var newUploads = Object.keys(state.files).filter(function (fileID) {
                        return !prevState.files.hasOwnProperty(fileID);
                    }).map(function (fileID) {
                        return state.files[fileID];
                    });
                    var newResults = state.results.filter(function (result) {
                        return !prevState.results.some(function (prev) {
                            return prev.id === result.id;
                        });
                    });

                    _this7.uppy.log('[Transloadit] New fully uploaded files since restore:');
                    _this7.uppy.log(newUploads);
                    newUploads.forEach(function (_ref2) {
                        var assembly = _ref2.assembly,
                            uploadedFile = _ref2.uploadedFile;

                        _this7.uppy.log('[Transloadit]  emitting transloadit:upload ' + uploadedFile.id);
                        _this7.uppy.emit('transloadit:upload', uploadedFile, _this7.getAssembly(assembly));
                    });
                    _this7.uppy.log('[Transloadit] New results since restore:');
                    _this7.uppy.log(newResults);
                    newResults.forEach(function (_ref3) {
                        var assembly = _ref3.assembly,
                            stepName = _ref3.stepName,
                            result = _ref3.result,
                            id = _ref3.id;

                        _this7.uppy.log('[Transloadit]  emitting transloadit:result ' + stepName + ', ' + id);
                        _this7.uppy.emit('transloadit:result', stepName, result, _this7.getAssembly(assembly));
                    });

                    var newAssemblies = state.assemblies;
                    var previousAssemblies = prevState.assemblies;
                    _this7.uppy.log('[Transloadit] Current assembly status after restore');
                    _this7.uppy.log(newAssemblies);
                    _this7.uppy.log('[Transloadit] Assembly status before restore');
                    _this7.uppy.log(previousAssemblies);
                    Object.keys(newAssemblies).forEach(function (assemblyId) {
                        var oldAssembly = previousAssemblies[assemblyId];
                        diffAssemblyStatus(oldAssembly, newAssemblies[assemblyId]);
                    });
                };

                // Emit events for assemblies that have completed or errored while we were away.
                var diffAssemblyStatus = function diffAssemblyStatus(prev, next) {
                    _this7.uppy.log('[Transloadit] Diff assemblies');
                    _this7.uppy.log(prev);
                    _this7.uppy.log(next);

                    if (opts.waitForEncoding && next.ok === 'ASSEMBLY_COMPLETED' && prev.ok !== 'ASSEMBLY_COMPLETED') {
                        _this7.uppy.log('[Transloadit]  Emitting transloadit:complete for ' + next.assembly_id);
                        _this7.uppy.log(next);
                        _this7.uppy.emit('transloadit:complete', next);
                    } else if (opts.waitForMetadata && next.upload_meta_data_extracted && !prev.upload_meta_data_extracted) {
                        _this7.uppy.log('[Transloadit]  Emitting transloadit:complete after metadata extraction for ' + next.assembly_id);
                        _this7.uppy.log(next);
                        _this7.uppy.emit('transloadit:complete', next);
                    }

                    if (next.error && !prev.error) {
                        _this7.uppy.log('[Transloadit]  !!! Emitting transloadit:assembly-error for ' + next.assembly_id);
                        _this7.uppy.log(next);
                        _this7.uppy.emit('transloadit:assembly-error', next, new Error(next.message));
                    }
                };

                emitMissedEvents();
            };

            Transloadit.prototype.onRestored = function onRestored(pluginData) {
                var _this8 = this;

                var savedState = pluginData && pluginData[this.id] ? pluginData[this.id] : {};
                var knownUploads = savedState.files || [];
                var knownResults = savedState.results || [];
                var previousAssemblies = savedState.assemblies || {};
                var uploadsAssemblies = savedState.uploadsAssemblies || {};

                if (Object.keys(uploadsAssemblies).length === 0) {
                    // Nothing to restore.
                    return;
                }

                // Fetch up-to-date assembly statuses.
                var loadAssemblies = function loadAssemblies() {
                    var assemblyIDs = [];
                    Object.keys(uploadsAssemblies).forEach(function (uploadID) {
                        assemblyIDs.push.apply(assemblyIDs, uploadsAssemblies[uploadID]);
                    });

                    return _Promise.all(assemblyIDs.map(function (assemblyID) {
                        var url = 'https://api2.transloadit.com/assemblies/' + assemblyID;
                        return _this8.client.getAssemblyStatus(url);
                    }));
                };

                var reconnectSockets = function reconnectSockets(assemblies) {
                    return _Promise.all(assemblies.map(function (assembly) {
                        // No need to connect to the socket if the assembly has completed by now.
                        if (assembly.ok === 'ASSEMBLY_COMPLETE') {
                            return null;
                        }
                        return _this8.connectSocket(assembly);
                    }));
                };

                // Convert loaded assembly statuses to a Transloadit plugin state object.
                var restoreState = function restoreState(assemblies) {
                    var assembliesById = {};
                    var files = {};
                    var results = [];
                    assemblies.forEach(function (assembly) {
                        assembliesById[assembly.assembly_id] = assembly;

                        assembly.uploads.forEach(function (uploadedFile) {
                            var file = _this8.findFile(uploadedFile);
                            files[uploadedFile.id] = {
                                id: file.id,
                                assembly: assembly.assembly_id,
                                uploadedFile: uploadedFile
                            };
                        });

                        var state = _this8.getPluginState();
                        Object.keys(assembly.results).forEach(function (stepName) {
                            assembly.results[stepName].forEach(function (result) {
                                var file = state.files[result.original_id];
                                result.localId = file ? file.id : null;
                                results.push({
                                    id: result.id,
                                    result: result,
                                    stepName: stepName,
                                    assembly: assembly.assembly_id
                                });
                            });
                        });
                    });

                    _this8.setPluginState({
                        assemblies: assembliesById,
                        files: files,
                        results: results,
                        uploadsAssemblies: uploadsAssemblies
                    });
                };

                // Restore all assembly state.
                this.restored = _Promise.resolve().then(loadAssemblies).then(function (assemblies) {
                    restoreState(assemblies);
                    return reconnectSockets(assemblies);
                }).then(function () {
                    // Return a callback that will be called by `afterUpload`
                    // once it has attached event listeners etc.
                    var newState = _this8.getPluginState();
                    var previousFiles = {};
                    knownUploads.forEach(function (id) {
                        previousFiles[id] = newState.files[id];
                    });
                    return function () {
                        return _this8.emitEventsDiff({
                            assemblies: previousAssemblies,
                            files: previousFiles,
                            results: newState.results.filter(function (_ref4) {
                                var id = _ref4.id;
                                return knownResults.indexOf(id) !== -1;
                            }),
                            uploadsAssemblies: uploadsAssemblies
                        });
                    };
                });

                this.restored.then(function () {
                    _this8.restored = null;
                });
            };

            Transloadit.prototype.connectSocket = function connectSocket(assembly) {
                var _this9 = this;

                var socket = new StatusSocket(assembly.websocket_url, assembly);
                this.sockets[assembly.assembly_id] = socket;

                socket.on('upload', this.onFileUploadComplete.bind(this, assembly.assembly_id));
                socket.on('error', function (error) {
                    _this9.uppy.emit('transloadit:assembly-error', assembly, error);
                });

                socket.on('executing', function () {
                    _this9.uppy.emit('transloadit:assembly-executing', assembly);
                });

                if (this.opts.waitForEncoding) {
                    socket.on('result', this.onResult.bind(this, assembly.assembly_id));
                }

                if (this.opts.waitForEncoding) {
                    socket.on('finished', function () {
                        _this9.onAssemblyFinished(assembly.assembly_ssl_url);
                    });
                } else if (this.opts.waitForMetadata) {
                    socket.on('metadata', function () {
                        _this9.onAssemblyFinished(assembly.assembly_ssl_url);
                    });
                }

                return new _Promise(function (resolve, reject) {
                    socket.on('connect', resolve);
                    socket.on('error', reject);
                }).then(function () {
                    _this9.uppy.log('[Transloadit] Socket is ready');
                });
            };

            Transloadit.prototype.prepareUpload = function prepareUpload(fileIDs, uploadID) {
                var _this10 = this,
                    _extends6;

                // Only use files without errors
                fileIDs = fileIDs.filter(function (file) {
                    return !file.error;
                });

                fileIDs.forEach(function (fileID) {
                    _this10.uppy.emit('preprocess-progress', fileID, {
                        mode: 'indeterminate',
                        message: _this10.i18n('creatingAssembly')
                    });
                });

                var createAssembly = function createAssembly(_ref5) {
                    var fileIDs = _ref5.fileIDs,
                        options = _ref5.options;

                    return _this10.createAssembly(fileIDs, uploadID, options).then(function (assembly) {
                        if (_this10.opts.importFromUploadURLs) {
                            return _this10.reserveFiles(assembly, fileIDs);
                        }
                    }).then(function () {
                        fileIDs.forEach(function (fileID) {
                            _this10.uppy.emit('preprocess-complete', fileID);
                        });
                    });
                };

                var state = this.getPluginState();
                var uploadsAssemblies = _extends({}, state.uploadsAssemblies, (_extends6 = {}, _extends6[uploadID] = [], _extends6));
                this.setPluginState({ uploadsAssemblies: uploadsAssemblies });

                var optionsPromise = void 0;
                if (fileIDs.length > 0) {
                    optionsPromise = this.getAssemblyOptions(fileIDs).then(function (allOptions) {
                        return _this10.dedupeAssemblyOptions(allOptions);
                    });
                } else if (this.opts.alwaysRunAssembly) {
                    optionsPromise = _Promise.resolve(this.opts.getAssemblyOptions(null, this.opts)).then(function (options) {
                        _this10.validateParams(options.params);
                        return [{ fileIDs: fileIDs, options: options }];
                    });
                } else {
                    // If there are no files and we do not `alwaysRunAssembly`,
                    // don't do anything.
                    return _Promise.resolve();
                }

                return optionsPromise.then(function (assemblies) {
                    return _Promise.all(assemblies.map(createAssembly));
                });
            };

            Transloadit.prototype.afterUpload = function afterUpload(fileIDs, uploadID) {
                var _this11 = this;

                // Only use files without errors
                fileIDs = fileIDs.filter(function (file) {
                    return !file.error;
                });

                var state = this.getPluginState();

                // If we're still restoring state, wait for that to be done.
                if (this.restored) {
                    return this.restored.then(function (emitMissedEvents) {
                        var promise = _this11.afterUpload(fileIDs, uploadID);
                        emitMissedEvents();
                        return promise;
                    });
                }

                var assemblyIDs = state.uploadsAssemblies[uploadID];

                // If we don't have to wait for encoding metadata or results, we can close
                // the socket immediately and finish the upload.
                if (!this.shouldWait()) {
                    assemblyIDs.forEach(function (assemblyID) {
                        var socket = _this11.sockets[assemblyID];
                        socket.close();
                    });
                    var assemblies = assemblyIDs.map(function (id) {
                        return _this11.getAssembly(id);
                    });
                    this.uppy.addResultData(uploadID, { transloadit: assemblies });
                    return _Promise.resolve();
                }

                // If no assemblies were created for this upload, we also do not have to wait.
                // There's also no sockets or anything to close, so just return immediately.
                if (assemblyIDs.length === 0) {
                    this.uppy.addResultData(uploadID, { transloadit: [] });
                    return _Promise.resolve();
                }

                var finishedAssemblies = 0;

                return new _Promise(function (resolve, reject) {
                    fileIDs.forEach(function (fileID) {
                        _this11.uppy.emit('postprocess-progress', fileID, {
                            mode: 'indeterminate',
                            message: _this11.i18n('encoding')
                        });
                    });

                    var onAssemblyFinished = function onAssemblyFinished(assembly) {
                        // An assembly for a different upload just finished. We can ignore it.
                        if (assemblyIDs.indexOf(assembly.assembly_id) === -1) {
                            _this11.uppy.log('[Transloadit] afterUpload(): Ignoring finished assembly ' + assembly.assembly_id);
                            return;
                        }
                        _this11.uppy.log('[Transloadit] afterUpload(): Got assembly finish ' + assembly.assembly_id);

                        // TODO set the `file.uploadURL` to a result?
                        // We will probably need an option here so the plugin user can tell us
                        // which result to pickâ€¦?

                        var files = _this11.getAssemblyFiles(assembly.assembly_id);
                        files.forEach(function (file) {
                            _this11.uppy.emit('postprocess-complete', file.id);
                        });

                        checkAllComplete();
                    };

                    var onAssemblyError = function onAssemblyError(assembly, error) {
                        // An assembly for a different upload just errored. We can ignore it.
                        if (assemblyIDs.indexOf(assembly.assembly_id) === -1) {
                            _this11.uppy.log('[Transloadit] afterUpload(): Ignoring errored assembly ' + assembly.assembly_id);
                            return;
                        }
                        _this11.uppy.log('[Transloadit] afterUpload(): Got assembly error ' + assembly.assembly_id);
                        _this11.uppy.log(error);

                        // Clear postprocessing state for all our files.
                        var files = _this11.getAssemblyFiles(assembly.assembly_id);
                        files.forEach(function (file) {
                            // TODO Maybe make a postprocess-error event here?
                            _this11.uppy.emit('upload-error', file.id, error);

                            _this11.uppy.emit('postprocess-complete', file.id);
                        });

                        checkAllComplete();
                    };

                    var onImportError = function onImportError(assembly, fileID, error) {
                        if (assemblyIDs.indexOf(assembly.assembly_id) === -1) {
                            return;
                        }

                        // Not sure if we should be doing something when it's just one file failing.
                        // ATM, the only options are 1) ignoring or 2) failing the entire upload.
                        // I think failing the upload is better than silently ignoring.
                        // In the future we should maybe have a way to resolve uploads with some failures,
                        // like returning an object with `{ successful, failed }` uploads.
                        onAssemblyError(assembly, error);
                    };

                    var checkAllComplete = function checkAllComplete() {
                        finishedAssemblies += 1;
                        if (finishedAssemblies === assemblyIDs.length) {
                            // We're done, these listeners can be removed
                            removeListeners();
                            var _assemblies = assemblyIDs.map(function (id) {
                                return _this11.getAssembly(id);
                            });
                            _this11.uppy.addResultData(uploadID, { transloadit: _assemblies });
                            resolve();
                        }
                    };

                    var removeListeners = function removeListeners() {
                        _this11.uppy.off('transloadit:complete', onAssemblyFinished);
                        _this11.uppy.off('transloadit:assembly-error', onAssemblyError);
                        _this11.uppy.off('transloadit:import-error', onImportError);
                    };

                    _this11.uppy.on('transloadit:complete', onAssemblyFinished);
                    _this11.uppy.on('transloadit:assembly-error', onAssemblyError);
                    _this11.uppy.on('transloadit:import-error', onImportError);
                }).then(function (result) {
                    // Clean up uploadID â†’ assemblyIDs, they're no longer going to be used anywhere.
                    var state = _this11.getPluginState();
                    var uploadsAssemblies = _extends({}, state.uploadsAssemblies);
                    delete uploadsAssemblies[uploadID];
                    _this11.setPluginState({ uploadsAssemblies: uploadsAssemblies });

                    return result;
                });
            };

            Transloadit.prototype.install = function install() {
                this.uppy.addPreProcessor(this.prepareUpload);
                this.uppy.addPostProcessor(this.afterUpload);

                if (this.opts.importFromUploadURLs) {
                    this.uppy.on('upload-success', this.onFileUploadURLAvailable);
                }

                this.uppy.on('restore:get-data', this.getPersistentData);
                this.uppy.on('restored', this.onRestored);

                this.setPluginState({
                    // Contains assembly status objects, indexed by their ID.
                    assemblies: {},
                    // Contains arrays of assembly IDs, indexed by the upload ID that they belong to.
                    uploadsAssemblies: {},
                    // Contains file data from Transloadit, indexed by their Transloadit-assigned ID.
                    files: {},
                    // Contains result data from Transloadit.
                    results: []
                });
            };

            Transloadit.prototype.uninstall = function uninstall() {
                this.uppy.removePreProcessor(this.prepareUpload);
                this.uppy.removePostProcessor(this.afterUpload);

                if (this.opts.importFromUploadURLs) {
                    this.uppy.off('upload-success', this.onFileUploadURLAvailable);
                }
            };

            Transloadit.prototype.getAssembly = function getAssembly(id) {
                var state = this.getPluginState();
                return state.assemblies[id];
            };

            Transloadit.prototype.getAssemblyFiles = function getAssemblyFiles(assemblyID) {
                var _this12 = this;

                var fileIDs = Object.keys(this.uppy.state.files);
                return fileIDs.map(function (fileID) {
                    return _this12.uppy.getFile(fileID);
                }).filter(function (file) {
                    return file && file.transloadit && file.transloadit.assembly === assemblyID;
                });
            };

            return Transloadit;
        }(Plugin);

    },{"../../core/Plugin":74,"../../core/Translator":75,"./Client":119,"./Socket":120,"es6-promise":33}],122:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var Plugin = require('../core/Plugin');
        var tus = require('tus-js-client');
        var UppySocket = require('../core/UppySocket');

        var _require = require('../core/Utils'),
            emitSocketProgress = _require.emitSocketProgress,
            getSocketHost = _require.getSocketHost,
            settle = _require.settle;

        require('whatwg-fetch');

// Extracted from https://github.com/tus/tus-js-client/blob/master/lib/upload.js#L13
// excepted we removed 'fingerprint' key to avoid adding more dependencies
        var tusDefaultOptions = {
            endpoint: '',
            resume: true,
            onProgress: null,
            onChunkComplete: null,
            onSuccess: null,
            onError: null,
            headers: {},
            chunkSize: Infinity,
            withCredentials: false,
            uploadUrl: null,
            uploadSize: null,
            overridePatchMethod: false,
            retryDelays: null

            /**
             * Create a wrapper around an event emitter with a `remove` method to remove
             * all events that were added using the wrapped emitter.
             */
        };function createEventTracker(emitter) {
            var events = [];
            return {
                on: function on(event, fn) {
                    events.push([event, fn]);
                    return emitter.on(event, fn);
                },
                remove: function remove() {
                    events.forEach(function (_ref) {
                        var event = _ref[0],
                            fn = _ref[1];

                        emitter.off(event, fn);
                    });
                }
            };
        }

        /**
         * Tus resumable file uploader
         *
         */
        module.exports = function (_Plugin) {
            _inherits(Tus, _Plugin);

            function Tus(uppy, opts) {
                _classCallCheck(this, Tus);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'uploader';
                _this.id = 'Tus';
                _this.title = 'Tus';

                // set default options
                var defaultOptions = {
                    resume: true,
                    autoRetry: true,
                    retryDelays: [0, 1000, 3000, 5000]

                    // merge default options with the ones set by user
                };_this.opts = _extends({}, defaultOptions, opts);

                _this.uploaders = Object.create(null);
                _this.uploaderEvents = Object.create(null);
                _this.uploaderSockets = Object.create(null);

                _this.handleResetProgress = _this.handleResetProgress.bind(_this);
                _this.handleUpload = _this.handleUpload.bind(_this);
                return _this;
            }

            Tus.prototype.handleResetProgress = function handleResetProgress() {
                var files = _extends({}, this.uppy.state.files);
                Object.keys(files).forEach(function (fileID) {
                    // Only clone the file object if it has a Tus `uploadUrl` attached.
                    if (files[fileID].tus && files[fileID].tus.uploadUrl) {
                        var tusState = _extends({}, files[fileID].tus);
                        delete tusState.uploadUrl;
                        files[fileID] = _extends({}, files[fileID], { tus: tusState });
                    }
                });

                this.uppy.setState({ files: files });
            };

            /**
             * Clean up all references for a file's upload: the tus.Upload instance,
             * any events related to the file, and the uppy-server WebSocket connection.
             */


            Tus.prototype.resetUploaderReferences = function resetUploaderReferences(fileID) {
                if (this.uploaders[fileID]) {
                    this.uploaders[fileID].abort();
                    this.uploaders[fileID] = null;
                }
                if (this.uploaderEvents[fileID]) {
                    this.uploaderEvents[fileID].remove();
                    this.uploaderEvents[fileID] = null;
                }
                if (this.uploaderSockets[fileID]) {
                    this.uploaderSockets[fileID].close();
                    this.uploaderSockets[fileID] = null;
                }
            };

            /**
             * Create a new Tus upload
             *
             * @param {object} file for use with upload
             * @param {integer} current file in a queue
             * @param {integer} total number of files in a queue
             * @returns {Promise}
             */


            Tus.prototype.upload = function upload(file, current, total) {
                var _this2 = this;

                this.resetUploaderReferences(file.id);

                // Create a new tus upload
                return new _Promise(function (resolve, reject) {
                    var optsTus = _extends({}, tusDefaultOptions, _this2.opts,
                        // Install file-specific upload overrides.
                        file.tus || {});

                    optsTus.onError = function (err) {
                        _this2.uppy.log(err);
                        _this2.uppy.emit('upload-error', file.id, err);
                        err.message = 'Failed because: ' + err.message;

                        _this2.resetUploaderReferences(file.id);
                        reject(err);
                    };

                    optsTus.onProgress = function (bytesUploaded, bytesTotal) {
                        _this2.onReceiveUploadUrl(file, upload.url);
                        _this2.uppy.emit('upload-progress', {
                            uploader: _this2,
                            id: file.id,
                            bytesUploaded: bytesUploaded,
                            bytesTotal: bytesTotal
                        });
                    };

                    optsTus.onSuccess = function () {
                        _this2.uppy.emit('upload-success', file.id, upload, upload.url);

                        if (upload.url) {
                            _this2.uppy.log('Download ' + upload.file.name + ' from ' + upload.url);
                        }

                        _this2.resetUploaderReferences(file.id);
                        resolve(upload);
                    };
                    optsTus.metadata = file.meta;

                    var upload = new tus.Upload(file.data, optsTus);
                    _this2.uploaders[file.id] = upload;
                    _this2.uploaderEvents[file.id] = createEventTracker(_this2.uppy);

                    _this2.onFileRemove(file.id, function (targetFileID) {
                        _this2.resetUploaderReferences(file.id);
                        resolve('upload ' + targetFileID + ' was removed');
                    });

                    _this2.onPause(file.id, function (isPaused) {
                        if (isPaused) {
                            upload.abort();
                        } else {
                            upload.start();
                        }
                    });

                    _this2.onPauseAll(file.id, function () {
                        upload.abort();
                    });

                    _this2.onCancelAll(file.id, function () {
                        _this2.resetUploaderReferences(file.id);
                    });

                    _this2.onResumeAll(file.id, function () {
                        if (file.error) {
                            upload.abort();
                        }
                        upload.start();
                    });

                    if (!file.isPaused) {
                        upload.start();
                    }
                    if (!file.isRestored) {
                        _this2.uppy.emit('upload-started', file.id, upload);
                    }
                });
            };

            Tus.prototype.uploadRemote = function uploadRemote(file, current, total) {
                var _this3 = this;

                this.resetUploaderReferences(file.id);

                return new _Promise(function (resolve, reject) {
                    _this3.uppy.log(file.remote.url);
                    if (file.serverToken) {
                        return _this3.connectToServerSocket(file).then(function () {
                            return resolve();
                        }).catch(reject);
                    }

                    var endpoint = _this3.opts.endpoint;
                    if (file.tus && file.tus.endpoint) {
                        endpoint = file.tus.endpoint;
                    }

                    _this3.uppy.emit('upload-started', file.id);

                    fetch(file.remote.url, {
                        method: 'post',
                        credentials: 'include',
                        headers: {
                            'Accept': 'application/json',
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify(_extends({}, file.remote.body, {
                            endpoint: endpoint,
                            protocol: 'tus',
                            size: file.data.size,
                            metadata: file.meta
                        }))
                    }).then(function (res) {
                        if (res.status < 200 || res.status > 300) {
                            return reject(res.statusText);
                        }

                        return res.json().then(function (data) {
                            _this3.uppy.setFileState(file.id, { serverToken: data.token });
                            file = _this3.getFile(file.id);
                            return file;
                        });
                    }).then(function (file) {
                        return _this3.connectToServerSocket(file);
                    }).then(function () {
                        resolve();
                    }).catch(function (err) {
                        reject(new Error(err));
                    });
                });
            };

            Tus.prototype.connectToServerSocket = function connectToServerSocket(file) {
                var _this4 = this;

                return new _Promise(function (resolve, reject) {
                    var token = file.serverToken;
                    var host = getSocketHost(file.remote.host);
                    var socket = new UppySocket({ target: host + '/api/' + token });
                    _this4.uploaderSockets[file.id] = socket;
                    _this4.uploaderEvents[file.id] = createEventTracker(_this4.uppy);

                    _this4.onFileRemove(file.id, function () {
                        socket.send('pause', {});
                        resolve('upload ' + file.id + ' was removed');
                    });

                    _this4.onPause(file.id, function (isPaused) {
                        isPaused ? socket.send('pause', {}) : socket.send('resume', {});
                    });

                    _this4.onPauseAll(file.id, function () {
                        return socket.send('pause', {});
                    });

                    _this4.onCancelAll(file.id, function () {
                        return socket.send('pause', {});
                    });

                    _this4.onResumeAll(file.id, function () {
                        if (file.error) {
                            socket.send('pause', {});
                        }
                        socket.send('resume', {});
                    });

                    _this4.onRetry(file.id, function () {
                        socket.send('pause', {});
                        socket.send('resume', {});
                    });

                    _this4.onRetryAll(file.id, function () {
                        socket.send('pause', {});
                        socket.send('resume', {});
                    });

                    if (file.isPaused) {
                        socket.send('pause', {});
                    }

                    socket.on('progress', function (progressData) {
                        return emitSocketProgress(_this4, progressData, file);
                    });

                    socket.on('error', function (errData) {
                        _this4.uppy.emit('upload-error', file.id, new Error(errData.error));
                        reject(new Error(errData.error));
                    });

                    socket.on('success', function (data) {
                        _this4.uppy.emit('upload-success', file.id, data, data.url);
                        _this4.resetUploaderReferences(file.id);
                        resolve();
                    });
                });
            };

            Tus.prototype.getFile = function getFile(fileID) {
                return this.uppy.state.files[fileID];
            };

            Tus.prototype.updateFile = function updateFile(file) {
                var _extends2;

                var files = _extends({}, this.uppy.state.files, (_extends2 = {}, _extends2[file.id] = file, _extends2));
                this.uppy.setState({ files: files });
            };

            Tus.prototype.onReceiveUploadUrl = function onReceiveUploadUrl(file, uploadURL) {
                var currentFile = this.getFile(file.id);
                if (!currentFile) return;
                // Only do the update if we didn't have an upload URL yet,
                // or resume: false in options
                if ((!currentFile.tus || currentFile.tus.uploadUrl !== uploadURL) && this.opts.resume) {
                    this.uppy.log('[Tus] Storing upload url');
                    var newFile = _extends({}, currentFile, {
                        tus: _extends({}, currentFile.tus, {
                            uploadUrl: uploadURL
                        })
                    });
                    this.updateFile(newFile);
                }
            };

            Tus.prototype.onFileRemove = function onFileRemove(fileID, cb) {
                this.uploaderEvents[fileID].on('file-removed', function (targetFileID) {
                    if (fileID === targetFileID) cb(targetFileID);
                });
            };

            Tus.prototype.onPause = function onPause(fileID, cb) {
                this.uploaderEvents[fileID].on('upload-pause', function (targetFileID, isPaused) {
                    if (fileID === targetFileID) {
                        // const isPaused = this.uppy.pauseResume(fileID)
                        cb(isPaused);
                    }
                });
            };

            Tus.prototype.onRetry = function onRetry(fileID, cb) {
                this.uploaderEvents[fileID].on('upload-retry', function (targetFileID) {
                    if (fileID === targetFileID) {
                        cb();
                    }
                });
            };

            Tus.prototype.onRetryAll = function onRetryAll(fileID, cb) {
                var _this5 = this;

                this.uploaderEvents[fileID].on('retry-all', function (filesToRetry) {
                    if (!_this5.uppy.getFile(fileID)) return;
                    cb();
                });
            };

            Tus.prototype.onPauseAll = function onPauseAll(fileID, cb) {
                var _this6 = this;

                this.uploaderEvents[fileID].on('pause-all', function () {
                    if (!_this6.uppy.getFile(fileID)) return;
                    cb();
                });
            };

            Tus.prototype.onCancelAll = function onCancelAll(fileID, cb) {
                var _this7 = this;

                this.uploaderEvents[fileID].on('cancel-all', function () {
                    if (!_this7.uppy.getFile(fileID)) return;
                    cb();
                });
            };

            Tus.prototype.onResumeAll = function onResumeAll(fileID, cb) {
                var _this8 = this;

                this.uploaderEvents[fileID].on('resume-all', function () {
                    if (!_this8.uppy.getFile(fileID)) return;
                    cb();
                });
            };

            Tus.prototype.uploadFiles = function uploadFiles(files) {
                var _this9 = this;

                var promises = files.map(function (file, index) {
                    var current = parseInt(index, 10) + 1;
                    var total = files.length;

                    if (file.error) {
                        return _Promise.reject(new Error(file.error));
                    }

                    _this9.uppy.log('uploading ' + current + ' of ' + total);

                    if (file.isRemote) {
                        return _this9.uploadRemote(file, current, total);
                    } else {
                        return _this9.upload(file, current, total);
                    }
                });

                return settle(promises);
            };

            Tus.prototype.handleUpload = function handleUpload(fileIDs) {
                var _this10 = this;

                if (fileIDs.length === 0) {
                    this.uppy.log('Tus: no files to upload!');
                    return _Promise.resolve();
                }

                this.uppy.log('Tus is uploading...');
                var filesToUpload = fileIDs.map(function (fileID) {
                    return _this10.uppy.getFile(fileID);
                });

                return this.uploadFiles(filesToUpload).then(function () {
                    return null;
                });
            };

            Tus.prototype.addResumableUploadsCapabilityFlag = function addResumableUploadsCapabilityFlag() {
                var newCapabilities = _extends({}, this.uppy.getState().capabilities);
                newCapabilities.resumableUploads = true;
                this.uppy.setState({
                    capabilities: newCapabilities
                });
            };

            Tus.prototype.install = function install() {
                this.addResumableUploadsCapabilityFlag();
                this.uppy.addUploader(this.handleUpload);

                this.uppy.on('reset-progress', this.handleResetProgress);

                if (this.opts.autoRetry) {
                    this.uppy.on('back-online', this.uppy.retryAll);
                }
            };

            Tus.prototype.uninstall = function uninstall() {
                this.uppy.removeUploader(this.handleUpload);

                if (this.opts.autoRetry) {
                    this.uppy.off('back-online', this.uppy.retryAll);
                }
            };

            return Tus;
        }(Plugin);

    },{"../core/Plugin":74,"../core/UppySocket":76,"../core/Utils":77,"es6-promise":33,"tus-js-client":67,"whatwg-fetch":70}],123:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "100", height: "77", viewBox: "0 0 100 77" },
                h("path", { d: "M50 32c-7.168 0-13 5.832-13 13s5.832 13 13 13 13-5.832 13-13-5.832-13-13-13z" }),
                h("path", { d: "M87 13H72c0-7.18-5.82-13-13-13H41c-7.18 0-13 5.82-13 13H13C5.82 13 0 18.82 0 26v38c0 7.18 5.82 13 13 13h74c7.18 0 13-5.82 13-13V26c0-7.18-5.82-13-13-13zM50 68c-12.683 0-23-10.318-23-23s10.317-23 23-23 23 10.318 23 23-10.317 23-23 23z" })
            );
        };

    },{"preact":46}],124:[function(require,module,exports){
        'use strict';

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _require = require('preact'),
            h = _require.h,
            Component = _require.Component;

        var SnapshotButton = require('./SnapshotButton');
        var RecordButton = require('./RecordButton');

        function isModeAvailable(modes, mode) {
            return modes.indexOf(mode) !== -1;
        }

        var CameraScreen = function (_Component) {
            _inherits(CameraScreen, _Component);

            function CameraScreen() {
                _classCallCheck(this, CameraScreen);

                return _possibleConstructorReturn(this, _Component.apply(this, arguments));
            }

            CameraScreen.prototype.componentDidMount = function componentDidMount() {
                this.props.onFocus();
                this.btnContainer.firstChild.focus();
            };

            CameraScreen.prototype.componentWillUnmount = function componentWillUnmount() {
                this.props.onStop();
            };

            CameraScreen.prototype.render = function render() {
                var _this2 = this;

                var shouldShowRecordButton = this.props.supportsRecording && (isModeAvailable(this.props.modes, 'video-only') || isModeAvailable(this.props.modes, 'audio-only') || isModeAvailable(this.props.modes, 'video-audio'));
                var shouldShowSnapshotButton = isModeAvailable(this.props.modes, 'picture');

                return h(
                    'div',
                    { 'class': 'uppy uppy-Webcam-container' },
                    h(
                        'div',
                        { 'class': 'uppy-Webcam-videoContainer' },
                        h('video', { 'class': 'uppy-Webcam-video  ' + (this.props.mirror ? 'uppy-Webcam-video--mirrored' : ''), autoplay: true, muted: true, playsinline: true, srcObject: this.props.src || '' })
                    ),
                    h(
                        'div',
                        { 'class': 'uppy-Webcam-buttonContainer', ref: function ref(el) {
                                _this2.btnContainer = el;
                            } },
                        shouldShowSnapshotButton ? SnapshotButton(this.props) : null,
                        ' ',
                        shouldShowRecordButton ? RecordButton(this.props) : null
                    )
                );
            };

            return CameraScreen;
        }(Component);

        module.exports = CameraScreen;

    },{"./RecordButton":126,"./SnapshotButton":129,"preact":46}],125:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            return h(
                "div",
                { "class": "uppy-Webcam-permissons" },
                h(
                    "h1",
                    { "class": "uppy-Webcam-Title" },
                    "Please allow access to your camera"
                ),
                h(
                    "p",
                    null,
                    "You have been prompted to allow camera access from this site.",
                    h("br", null),
                    "In order to take pictures with your camera you must approve this request."
                )
            );
        };

    },{"preact":46}],126:[function(require,module,exports){
        'use strict';

        var RecordStartIcon = require('./RecordStartIcon');
        var RecordStopIcon = require('./RecordStopIcon');

        var _require = require('preact'),
            h = _require.h;

        module.exports = function RecordButton(_ref) {
            var recording = _ref.recording,
                onStartRecording = _ref.onStartRecording,
                onStopRecording = _ref.onStopRecording;

            if (recording) {
                return h(
                    'button',
                    { 'class': 'UppyButton--circular UppyButton--red UppyButton--sizeM uppy-Webcam-recordButton',
                        type: 'button',
                        title: 'Stop Recording',
                        'aria-label': 'Stop Recording',
                        onclick: onStopRecording },
                    RecordStopIcon()
                );
            }

            return h(
                'button',
                { 'class': 'UppyButton--circular UppyButton--red UppyButton--sizeM uppy-Webcam-recordButton',
                    type: 'button',
                    title: 'Begin Recording',
                    'aria-label': 'Begin Recording',
                    onclick: onStartRecording },
                RecordStartIcon()
            );
        };

    },{"./RecordStartIcon":127,"./RecordStopIcon":128,"preact":46}],127:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "100", height: "100", viewBox: "0 0 100 100" },
                h("circle", { cx: "50", cy: "50", r: "40" })
            );
        };

    },{"preact":46}],128:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "100", height: "100", viewBox: "0 0 100 100" },
                h("rect", { x: "15", y: "15", width: "70", height: "70" })
            );
        };

    },{"preact":46}],129:[function(require,module,exports){
        'use strict';

        var _require = require('preact'),
            h = _require.h;

        var CameraIcon = require('./CameraIcon');

        module.exports = function (_ref) {
            var onSnapshot = _ref.onSnapshot;

            return h(
                'button',
                { 'class': 'UppyButton--circular UppyButton--red UppyButton--sizeM uppy-Webcam-recordButton',
                    type: 'button',
                    title: 'Take a snapshot',
                    'aria-label': 'Take a snapshot',
                    onclick: onSnapshot },
                CameraIcon()
            );
        };

    },{"./CameraIcon":123,"preact":46}],130:[function(require,module,exports){
        "use strict";

        var _require = require('preact'),
            h = _require.h;

        module.exports = function (props) {
            return h(
                "svg",
                { "aria-hidden": "true", "class": "UppyIcon", width: "18", height: "21", viewBox: "0 0 18 21" },
                h("path", { d: "M14.8 16.9c1.9-1.7 3.2-4.1 3.2-6.9 0-5-4-9-9-9s-9 4-9 9c0 2.8 1.2 5.2 3.2 6.9C1.9 17.9.5 19.4 0 21h3c1-1.9 11-1.9 12 0h3c-.5-1.6-1.9-3.1-3.2-4.1zM9 4c3.3 0 6 2.7 6 6s-2.7 6-6 6-6-2.7-6-6 2.7-6 6-6z" }),
                h("path", { d: "M9 14c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4zM8 8c.6 0 1 .4 1 1s-.4 1-1 1-1-.4-1-1c0-.5.4-1 1-1z" })
            );
        };

    },{"preact":46}],131:[function(require,module,exports){
        'use strict';

        var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var _require = require('preact'),
            h = _require.h;

        var Plugin = require('../../core/Plugin');
        var Translator = require('../../core/Translator');

        var _require2 = require('../../core/Utils'),
            getFileTypeExtension = _require2.getFileTypeExtension,
            canvasToBlob = _require2.canvasToBlob;

        var supportsMediaRecorder = require('./supportsMediaRecorder');
        var WebcamIcon = require('./WebcamIcon');
        var CameraScreen = require('./CameraScreen');
        var PermissionsScreen = require('./PermissionsScreen');

// Setup getUserMedia, with polyfill for older browsers
// Adapted from: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
        function getMediaDevices() {
            if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
                return navigator.mediaDevices;
            }

            var _getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
            if (!_getUserMedia) {
                return null;
            }

            return {
                getUserMedia: function getUserMedia(opts) {
                    return new _Promise(function (resolve, reject) {
                        _getUserMedia.call(navigator, opts, resolve, reject);
                    });
                }
            };
        }

        /**
         * Webcam
         */
        module.exports = function (_Plugin) {
            _inherits(Webcam, _Plugin);

            function Webcam(uppy, opts) {
                _classCallCheck(this, Webcam);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.mediaDevices = getMediaDevices();
                _this.supportsUserMedia = !!_this.mediaDevices;
                _this.protocol = location.protocol.match(/https/i) ? 'https' : 'http';
                _this.id = _this.opts.id || 'Webcam';
                _this.title = 'Webcam';
                _this.type = 'acquirer';
                _this.icon = WebcamIcon;

                var defaultLocale = {
                    strings: {
                        smile: 'Smile!'
                    }

                    // set default options
                };var defaultOptions = {
                    onBeforeSnapshot: function onBeforeSnapshot() {
                        return _Promise.resolve();
                    },
                    countdown: false,
                    locale: defaultLocale,
                    modes: ['video-audio', 'video-only', 'audio-only', 'picture'],
                    mirror: true,
                    facingMode: 'user'

                    // merge default options with the ones set by user
                };_this.opts = _extends({}, defaultOptions, opts);

                _this.locale = _extends({}, defaultLocale, _this.opts.locale);
                _this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);

                // i18n
                _this.translator = new Translator({ locale: _this.locale });
                _this.i18n = _this.translator.translate.bind(_this.translator);

                _this.install = _this.install.bind(_this);
                _this.setPluginState = _this.setPluginState.bind(_this);

                _this.render = _this.render.bind(_this);

                // Camera controls
                _this.start = _this.start.bind(_this);
                _this.stop = _this.stop.bind(_this);
                _this.takeSnapshot = _this.takeSnapshot.bind(_this);
                _this.startRecording = _this.startRecording.bind(_this);
                _this.stopRecording = _this.stopRecording.bind(_this);
                _this.oneTwoThreeSmile = _this.oneTwoThreeSmile.bind(_this);
                _this.focus = _this.focus.bind(_this);

                _this.webcamActive = false;

                if (_this.opts.countdown) {
                    _this.opts.onBeforeSnapshot = _this.oneTwoThreeSmile;
                }
                return _this;
            }

            Webcam.prototype.isSupported = function isSupported() {
                return !!this.mediaDevices;
            };

            Webcam.prototype.getConstraints = function getConstraints() {
                var acceptsAudio = this.opts.modes.indexOf('video-audio') !== -1 || this.opts.modes.indexOf('audio-only') !== -1;
                var acceptsVideo = this.opts.modes.indexOf('video-audio') !== -1 || this.opts.modes.indexOf('video-only') !== -1 || this.opts.modes.indexOf('picture') !== -1;

                return {
                    audio: acceptsAudio,
                    video: acceptsVideo ? { facingMode: this.opts.facingMode } : false
                };
            };

            Webcam.prototype.start = function start() {
                var _this2 = this;

                if (!this.isSupported()) {
                    return _Promise.reject(new Error('Webcam access not supported'));
                }

                this.webcamActive = true;

                var constraints = this.getConstraints();

                // ask user for access to their camera
                return this.mediaDevices.getUserMedia(constraints).then(function (stream) {
                    _this2.stream = stream;
                    // this.streamSrc = URL.createObjectURL(this.stream)
                    _this2.setPluginState({
                        cameraReady: true
                    });
                }).catch(function (err) {
                    _this2.setPluginState({
                        cameraError: err
                    });
                });
            };

            Webcam.prototype.startRecording = function startRecording() {
                var _this3 = this;

                // TODO We can check here if any of the mime types listed in the
                // mimeToExtensions map in Utils.js are supported, and prefer to use one of
                // those.
                // Right now we let the browser pick a type that it deems appropriate.
                this.recorder = new MediaRecorder(this.stream);
                this.recordingChunks = [];
                this.recorder.addEventListener('dataavailable', function (event) {
                    _this3.recordingChunks.push(event.data);
                });
                this.recorder.start();

                this.setPluginState({
                    isRecording: true
                });
            };

            Webcam.prototype.stopRecording = function stopRecording() {
                var _this4 = this;

                var stopped = new _Promise(function (resolve, reject) {
                    _this4.recorder.addEventListener('stop', function () {
                        resolve();
                    });
                    _this4.recorder.stop();
                });

                return stopped.then(function () {
                    _this4.setPluginState({
                        isRecording: false
                    });
                    return _this4.getVideo();
                }).then(function (file) {
                    return _this4.uppy.addFile(file);
                }).then(function () {
                    _this4.recordingChunks = null;
                    _this4.recorder = null;
                    var dashboard = _this4.uppy.getPlugin('Dashboard');
                    if (dashboard) dashboard.hideAllPanels();
                }, function (error) {
                    _this4.recordingChunks = null;
                    _this4.recorder = null;
                    throw error;
                });
            };

            Webcam.prototype.stop = function stop() {
                this.stream.getAudioTracks().forEach(function (track) {
                    track.stop();
                });
                this.stream.getVideoTracks().forEach(function (track) {
                    track.stop();
                });
                this.webcamActive = false;
                this.stream = null;
            };

            Webcam.prototype.getVideoElement = function getVideoElement() {
                return this.el.querySelector('.uppy-Webcam-video');
            };

            Webcam.prototype.oneTwoThreeSmile = function oneTwoThreeSmile() {
                var _this5 = this;

                return new _Promise(function (resolve, reject) {
                    var count = _this5.opts.countdown;

                    var countDown = setInterval(function () {
                        if (!_this5.webcamActive) {
                            clearInterval(countDown);
                            _this5.captureInProgress = false;
                            return reject(new Error('Webcam is not active'));
                        }

                        if (count > 0) {
                            _this5.uppy.info(count + '...', 'warning', 800);
                            count--;
                        } else {
                            clearInterval(countDown);
                            _this5.uppy.info(_this5.i18n('smile'), 'success', 1500);
                            setTimeout(function () {
                                return resolve();
                            }, 1500);
                        }
                    }, 1000);
                });
            };

            Webcam.prototype.takeSnapshot = function takeSnapshot() {
                var _this6 = this;

                if (this.captureInProgress) return;
                this.captureInProgress = true;

                this.opts.onBeforeSnapshot().catch(function (err) {
                    var message = (typeof err === 'undefined' ? 'undefined' : _typeof(err)) === 'object' ? err.message : err;
                    _this6.uppy.info(message, 'error', 5000);
                    return _Promise.reject(new Error('onBeforeSnapshot: ' + message));
                }).then(function () {
                    return _this6.getImage();
                }).then(function (tagFile) {
                    _this6.captureInProgress = false;
                    var dashboard = _this6.uppy.getPlugin('Dashboard');
                    if (dashboard) dashboard.hideAllPanels();
                    return _this6.uppy.addFile(tagFile).catch(function () {
                        // Ignore
                    });
                }, function (error) {
                    _this6.captureInProgress = false;
                    throw error;
                });
            };

            Webcam.prototype.getImage = function getImage() {
                var _this7 = this;

                var video = this.getVideoElement();
                if (!video) {
                    return _Promise.reject(new Error('No video element found, likely due to the Webcam tab being closed.'));
                }

                var name = 'webcam-' + Date.now() + '.jpg';
                var mimeType = 'image/jpeg';

                var width = video.videoWidth;
                var height = video.videoHeight;

                // const scaleH = this.opts.mirror ? -1 : 1 // Set horizontal scale to -1 if flip horizontal
                // const scaleV = 1
                // const posX = this.opts.mirror ? width * -1 : 0 // Set x position to -100% if flip horizontal
                // const posY = 0

                var canvas = document.createElement('canvas');
                canvas.width = width;
                canvas.height = height;
                var ctx = canvas.getContext('2d');
                ctx.drawImage(video, 0, 0);
                // ctx.save() // Save the current state
                // ctx.scale(scaleH, scaleV) // Set scale to flip the image
                // ctx.drawImage(video, posX, posY, width, height) // draw the image
                // ctx.restore() // Restore the last saved state

                return canvasToBlob(canvas, mimeType).then(function (blob) {
                    return {
                        source: _this7.id,
                        name: name,
                        data: new File([blob], name, { type: mimeType }),
                        type: mimeType
                    };
                });
            };

            Webcam.prototype.getVideo = function getVideo() {
                var mimeType = this.recordingChunks[0].type;
                var fileExtension = getFileTypeExtension(mimeType);

                if (!fileExtension) {
                    return _Promise.reject(new Error('Could not retrieve recording: Unsupported media type "' + mimeType + '"'));
                }

                var name = 'webcam-' + Date.now() + '.' + fileExtension;
                var blob = new Blob(this.recordingChunks, { type: mimeType });
                var file = {
                    source: this.id,
                    name: name,
                    data: new File([blob], name, { type: mimeType }),
                    type: mimeType
                };

                return _Promise.resolve(file);
            };

            Webcam.prototype.focus = function focus() {
                var _this8 = this;

                if (this.opts.countdown) return;
                setTimeout(function () {
                    _this8.uppy.info(_this8.i18n('smile'), 'success', 1500);
                }, 1000);
            };

            Webcam.prototype.render = function render(state) {
                if (!this.webcamActive) {
                    this.start();
                }

                var webcamState = this.getPluginState();

                if (!webcamState.cameraReady) {
                    return PermissionsScreen(webcamState);
                }

                return h(CameraScreen, _extends({}, webcamState, {
                    onSnapshot: this.takeSnapshot,
                    onStartRecording: this.startRecording,
                    onStopRecording: this.stopRecording,
                    onFocus: this.focus,
                    onStop: this.stop,
                    modes: this.opts.modes,
                    supportsRecording: supportsMediaRecorder(),
                    recording: webcamState.isRecording,
                    mirror: this.opts.mirror,
                    src: this.stream
                }));
            };

            Webcam.prototype.install = function install() {
                this.setPluginState({
                    cameraReady: false
                });

                var target = this.opts.target;
                if (target) {
                    this.mount(target, this);
                }
            };

            Webcam.prototype.uninstall = function uninstall() {
                if (this.stream) {
                    this.stop();
                }

                this.unmount();
            };

            return Webcam;
        }(Plugin);

    },{"../../core/Plugin":74,"../../core/Translator":75,"../../core/Utils":77,"./CameraScreen":124,"./PermissionsScreen":125,"./WebcamIcon":130,"./supportsMediaRecorder":132,"es6-promise":33,"preact":46}],132:[function(require,module,exports){
        'use strict';

        module.exports = function supportsMediaRecorder() {
            return typeof MediaRecorder === 'function' && !!MediaRecorder.prototype && typeof MediaRecorder.prototype.start === 'function';
        };

    },{}],133:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

        function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

        var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;

        var Plugin = require('../core/Plugin');
        var cuid = require('cuid');
        var Translator = require('../core/Translator');
        var UppySocket = require('../core/UppySocket');

        var _require = require('../core/Utils'),
            emitSocketProgress = _require.emitSocketProgress,
            getSocketHost = _require.getSocketHost,
            settle = _require.settle,
            limitPromises = _require.limitPromises;

        module.exports = function (_Plugin) {
            _inherits(XHRUpload, _Plugin);

            function XHRUpload(uppy, opts) {
                _classCallCheck(this, XHRUpload);

                var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));

                _this.type = 'uploader';
                _this.id = 'XHRUpload';
                _this.title = 'XHRUpload';

                var defaultLocale = {
                    strings: {
                        timedOut: 'Upload stalled for %{seconds} seconds, aborting.'
                    }

                    // Default options
                };var defaultOptions = {
                    formData: true,
                    fieldName: 'files[]',
                    method: 'post',
                    metaFields: null,
                    responseUrlFieldName: 'url',
                    bundle: false,
                    headers: {},
                    locale: defaultLocale,
                    timeout: 30 * 1000,
                    limit: 0,
                    /**
                     * @typedef respObj
                     * @property {string} responseText
                     * @property {number} status
                     * @property {string} statusText
                     * @property {Object.<string, string>} headers
                     *
                     * @param {string} responseContent the response body
                     * @param {XMLHttpRequest | respObj} responseObject the response object
                     */
                    getResponseData: function getResponseData(responseContent, responseObject) {
                        var response = {};
                        try {
                            response = JSON.parse(responseContent);
                        } catch (err) {
                            this.uppy.log(err, 'error');
                        }

                        return response;
                    },

                    /**
                     *
                     * @param {string} responseContent the response body
                     * @param {XMLHttpRequest | respObj} responseObject the response object
                     */
                    getResponseError: function getResponseError(responseContent, responseObject) {
                        return new Error('Upload error');
                    }
                };

                // Merge default options with the ones set by user
                _this.opts = _extends({}, defaultOptions, opts);
                _this.locale = _extends({}, defaultLocale, _this.opts.locale);
                _this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);

                // i18n
                _this.translator = new Translator({ locale: _this.locale });
                _this.i18n = _this.translator.translate.bind(_this.translator);

                _this.handleUpload = _this.handleUpload.bind(_this);

                // Simultaneous upload limiting is shared across all uploads with this plugin.
                if (typeof _this.opts.limit === 'number' && _this.opts.limit !== 0) {
                    _this.limitUploads = limitPromises(_this.opts.limit);
                } else {
                    _this.limitUploads = function (fn) {
                        return fn;
                    };
                }

                if (_this.opts.bundle && !_this.opts.formData) {
                    throw new Error('`opts.formData` must be true when `opts.bundle` is enabled.');
                }
                return _this;
            }

            XHRUpload.prototype.getOptions = function getOptions(file) {
                var opts = _extends({}, this.opts, this.uppy.state.xhrUpload || {}, file.xhrUpload || {});
                opts.headers = {};
                _extends(opts.headers, this.opts.headers);
                if (this.uppy.state.xhrUpload) {
                    _extends(opts.headers, this.uppy.state.xhrUpload.headers);
                }
                if (file.xhrUpload) {
                    _extends(opts.headers, file.xhrUpload.headers);
                }

                return opts;
            };

            // Helper to abort upload requests if there has not been any progress for `timeout` ms.
            // Create an instance using `timer = createProgressTimeout(10000, onTimeout)`
            // Call `timer.progress()` to signal that there has been progress of any kind.
            // Call `timer.done()` when the upload has completed.


            XHRUpload.prototype.createProgressTimeout = function createProgressTimeout(timeout, timeoutHandler) {
                var uppy = this.uppy;
                var self = this;
                function onTimedOut() {
                    uppy.log('[XHRUpload] timed out');
                    var error = new Error(self.i18n('timedOut', { seconds: Math.ceil(timeout / 1000) }));
                    timeoutHandler(error);
                }

                var aliveTimer = null;
                function progress() {
                    if (timeout > 0) {
                        done();
                        aliveTimer = setTimeout(onTimedOut, timeout);
                    }
                }

                function done() {
                    if (aliveTimer) {
                        clearTimeout(aliveTimer);
                        aliveTimer = null;
                    }
                }

                return {
                    progress: progress,
                    done: done
                };
            };

            XHRUpload.prototype.createFormDataUpload = function createFormDataUpload(file, opts) {
                var formPost = new FormData();

                var metaFields = Array.isArray(opts.metaFields) ? opts.metaFields
                    // Send along all fields by default.
                    : Object.keys(file.meta);
                metaFields.forEach(function (item) {
                    formPost.append(item, file.meta[item]);
                });

                formPost.append(opts.fieldName, file.data);

                return formPost;
            };

            XHRUpload.prototype.createBareUpload = function createBareUpload(file, opts) {
                return file.data;
            };

            XHRUpload.prototype.upload = function upload(file, current, total) {
                var _this2 = this;

                var opts = this.getOptions(file);

                this.uppy.log('uploading ' + current + ' of ' + total);
                return new _Promise(function (resolve, reject) {
                    var data = opts.formData ? _this2.createFormDataUpload(file, opts) : _this2.createBareUpload(file, opts);

                    var timer = _this2.createProgressTimeout(opts.timeout, function (error) {
                        xhr.abort();
                        _this2.uppy.emit('upload-error', file.id, error);
                        reject(error);
                    });

                    var xhr = new XMLHttpRequest();
                    var id = cuid();

                    xhr.upload.addEventListener('loadstart', function (ev) {
                        _this2.uppy.log('[XHRUpload] ' + id + ' started');
                        // Begin checking for timeouts when loading starts.
                        timer.progress();
                    });

                    xhr.upload.addEventListener('progress', function (ev) {
                        _this2.uppy.log('[XHRUpload] ' + id + ' progress: ' + ev.loaded + ' / ' + ev.total);
                        timer.progress();

                        if (ev.lengthComputable) {
                            _this2.uppy.emit('upload-progress', {
                                uploader: _this2,
                                id: file.id,
                                bytesUploaded: ev.loaded,
                                bytesTotal: ev.total
                            });
                        }
                    });

                    xhr.addEventListener('load', function (ev) {
                        _this2.uppy.log('[XHRUpload] ' + id + ' finished');
                        timer.done();

                        if (ev.target.status >= 200 && ev.target.status < 300) {
                            var resp = opts.getResponseData(xhr.responseText, xhr);
                            var uploadURL = resp[opts.responseUrlFieldName];

                            _this2.uppy.emit('upload-success', file.id, resp, uploadURL);

                            if (uploadURL) {
                                _this2.uppy.log('Download ' + file.name + ' from ' + file.uploadURL);
                            }

                            return resolve(file);
                        } else {
                            var error = opts.getResponseError(xhr.responseText, xhr) || new Error('Upload error');
                            error.request = xhr;
                            _this2.uppy.emit('upload-error', file.id, error);
                            return reject(error);
                        }
                    });

                    xhr.addEventListener('error', function (ev) {
                        _this2.uppy.log('[XHRUpload] ' + id + ' errored');
                        timer.done();

                        var error = opts.getResponseError(xhr.responseText, xhr) || new Error('Upload error');
                        _this2.uppy.emit('upload-error', file.id, error);
                        return reject(error);
                    });

                    xhr.open(opts.method.toUpperCase(), opts.endpoint, true);

                    Object.keys(opts.headers).forEach(function (header) {
                        xhr.setRequestHeader(header, opts.headers[header]);
                    });

                    xhr.send(data);

                    _this2.uppy.on('upload-cancel', function (fileID) {
                        if (fileID === file.id) {
                            xhr.abort();
                        }
                    });

                    _this2.uppy.on('cancel-all', function () {
                        // const files = this.uppy.getState().files
                        // if (!files[file.id]) return
                        xhr.abort();
                    });
                });
            };

            XHRUpload.prototype.uploadRemote = function uploadRemote(file, current, total) {
                var _this3 = this;

                var opts = this.getOptions(file);
                return new _Promise(function (resolve, reject) {
                    var fields = {};
                    var metaFields = Array.isArray(opts.metaFields) ? opts.metaFields
                        // Send along all fields by default.
                        : Object.keys(file.meta);

                    metaFields.forEach(function (name) {
                        fields[name] = file.meta[name];
                    });

                    fetch(file.remote.url, {
                        method: 'post',
                        credentials: 'include',
                        headers: {
                            'Accept': 'application/json',
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify(_extends({}, file.remote.body, {
                            endpoint: opts.endpoint,
                            size: file.data.size,
                            fieldname: opts.fieldName,
                            metadata: fields,
                            headers: opts.headers
                        }))
                    }).then(function (res) {
                        if (res.status < 200 && res.status > 300) {
                            return reject(res.statusText);
                        }

                        res.json().then(function (data) {
                            var token = data.token;
                            var host = getSocketHost(file.remote.host);
                            var socket = new UppySocket({ target: host + '/api/' + token });

                            socket.on('progress', function (progressData) {
                                return emitSocketProgress(_this3, progressData, file);
                            });

                            socket.on('success', function (data) {
                                var resp = opts.getResponseData(data.response.responseText, data.response);
                                var uploadURL = resp[opts.responseUrlFieldName];
                                _this3.uppy.emit('upload-success', file.id, resp, uploadURL);
                                socket.close();
                                return resolve();
                            });

                            socket.on('error', function (errData) {
                                var resp = errData.response;
                                var error = resp ? opts.getResponseError(resp.responseText, resp) : new Error(errData.error);
                                _this3.uppy.emit('upload-error', file.id, error);
                                reject(new Error(errData.error));
                            });
                        });
                    });
                });
            };

            XHRUpload.prototype.uploadBundle = function uploadBundle(files) {
                var _this4 = this;

                return new _Promise(function (resolve, reject) {
                    var endpoint = _this4.opts.endpoint;
                    var method = _this4.opts.method;

                    var formData = new FormData();
                    files.forEach(function (file, i) {
                        var opts = _this4.getOptions(file);
                        formData.append(opts.fieldName, file.data);
                    });

                    var xhr = new XMLHttpRequest();

                    var timer = _this4.createProgressTimeout(_this4.opts.timeout, function (error) {
                        xhr.abort();
                        emitError(error);
                        reject(error);
                    });

                    var emitError = function emitError(error) {
                        files.forEach(function (file) {
                            _this4.uppy.emit('upload-error', file.id, error);
                        });
                    };

                    xhr.upload.addEventListener('loadstart', function (ev) {
                        _this4.uppy.log('[XHRUpload] started uploading bundle');
                        timer.progress();
                    });

                    xhr.upload.addEventListener('progress', function (ev) {
                        timer.progress();

                        if (!ev.lengthComputable) return;

                        files.forEach(function (file) {
                            _this4.uppy.emit('upload-progress', {
                                uploader: _this4,
                                id: file.id,
                                bytesUploaded: ev.loaded,
                                bytesTotal: ev.total
                            });
                        });
                    });

                    xhr.addEventListener('load', function (ev) {
                        timer.done();

                        if (ev.target.status >= 200 && ev.target.status < 300) {
                            var resp = _this4.opts.getResponseData(xhr.responseText, xhr);
                            files.forEach(function (file) {
                                _this4.uppy.emit('upload-success', file.id, resp);
                            });
                            return resolve();
                        }

                        var error = _this4.opts.getResponseError(xhr.responseText, xhr) || new Error('Upload error');
                        error.request = xhr;
                        emitError(error);
                        return reject(error);
                    });

                    xhr.addEventListener('error', function (ev) {
                        timer.done();

                        var error = _this4.opts.getResponseError(xhr.responseText, xhr) || new Error('Upload error');
                        emitError(error);
                        return reject(error);
                    });

                    _this4.uppy.on('cancel-all', function () {
                        xhr.abort();
                    });

                    xhr.open(method.toUpperCase(), endpoint, true);

                    Object.keys(_this4.opts.headers).forEach(function (header) {
                        xhr.setRequestHeader(header, _this4.opts.headers[header]);
                    });

                    xhr.send(formData);

                    files.forEach(function (file) {
                        _this4.uppy.emit('upload-started', file.id);
                    });
                });
            };

            XHRUpload.prototype.uploadFiles = function uploadFiles(files) {
                var _this5 = this;

                var actions = files.map(function (file, i) {
                    var current = parseInt(i, 10) + 1;
                    var total = files.length;

                    if (file.error) {
                        return function () {
                            return _Promise.reject(new Error(file.error));
                        };
                    } else if (file.isRemote) {
                        // We emit upload-started here, so that it's also emitted for files
                        // that have to wait due to the `limit` option.
                        _this5.uppy.emit('upload-started', file.id);
                        return _this5.uploadRemote.bind(_this5, file, current, total);
                    } else {
                        _this5.uppy.emit('upload-started', file.id);
                        return _this5.upload.bind(_this5, file, current, total);
                    }
                });

                var promises = actions.map(function (action) {
                    var limitedAction = _this5.limitUploads(action);
                    return limitedAction();
                });

                return settle(promises);
            };

            XHRUpload.prototype.handleUpload = function handleUpload(fileIDs) {
                var _this6 = this;

                if (fileIDs.length === 0) {
                    this.uppy.log('[XHRUpload] No files to upload!');
                    return _Promise.resolve();
                }

                this.uppy.log('[XHRUpload] Uploading...');
                var files = fileIDs.map(function (fileID) {
                    return _this6.uppy.getFile(fileID);
                });

                if (this.opts.bundle) {
                    return this.uploadBundle(files);
                }

                return this.uploadFiles(files).then(function () {
                    return null;
                });
            };

            XHRUpload.prototype.install = function install() {
                this.uppy.addUploader(this.handleUpload);
            };

            XHRUpload.prototype.uninstall = function uninstall() {
                this.uppy.removeUploader(this.handleUpload);
            };

            return XHRUpload;
        }(Plugin);

    },{"../core/Plugin":74,"../core/Translator":75,"../core/UppySocket":76,"../core/Utils":77,"cuid":11,"es6-promise":33}],134:[function(require,module,exports){
        "use strict";

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

        /**
         * Default store that keeps state in a simple object.
         */
        var DefaultStore = function () {
            function DefaultStore() {
                _classCallCheck(this, DefaultStore);

                this.state = {};
                this.callbacks = [];
            }

            DefaultStore.prototype.getState = function getState() {
                return this.state;
            };

            DefaultStore.prototype.setState = function setState(patch) {
                var prevState = _extends({}, this.state);
                var nextState = _extends({}, this.state, patch);

                this.state = nextState;
                this._publish(prevState, nextState, patch);
            };

            DefaultStore.prototype.subscribe = function subscribe(listener) {
                var _this = this;

                this.callbacks.push(listener);
                return function () {
                    // Remove the listener.
                    _this.callbacks.splice(_this.callbacks.indexOf(listener), 1);
                };
            };

            DefaultStore.prototype._publish = function _publish() {
                for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                    args[_key] = arguments[_key];
                }

                this.callbacks.forEach(function (listener) {
                    listener.apply(undefined, args);
                });
            };

            return DefaultStore;
        }();

        module.exports = function defaultStore() {
            return new DefaultStore();
        };

    },{}],135:[function(require,module,exports){
        'use strict';

        var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

        module.exports = function (input) {
            var buf = new Uint8Array(input);

            if (!(buf && buf.length > 1)) {
                return null;
            }

            var check = function check(header, opts) {
                opts = _extends({
                    offset: 0
                }, opts);

                for (var i = 0; i < header.length; i++) {
                    if (header[i] !== buf[i + opts.offset]) {
                        return false;
                    }
                }

                return true;
            };

            if (check([0xFF, 0xD8, 0xFF])) {
                return {
                    ext: 'jpg',
                    mime: 'image/jpeg'
                };
            }

            if (check([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])) {
                return {
                    ext: 'png',
                    mime: 'image/png'
                };
            }

            if (check([0x47, 0x49, 0x46])) {
                return {
                    ext: 'gif',
                    mime: 'image/gif'
                };
            }

            if (check([0x57, 0x45, 0x42, 0x50], { offset: 8 })) {
                return {
                    ext: 'webp',
                    mime: 'image/webp'
                };
            }

            if (check([0x46, 0x4C, 0x49, 0x46])) {
                return {
                    ext: 'flif',
                    mime: 'image/flif'
                };
            }

            // Needs to be before `tif` check
            if ((check([0x49, 0x49, 0x2A, 0x0]) || check([0x4D, 0x4D, 0x0, 0x2A])) && check([0x43, 0x52], { offset: 8 })) {
                return {
                    ext: 'cr2',
                    mime: 'image/x-canon-cr2'
                };
            }

            if (check([0x49, 0x49, 0x2A, 0x0]) || check([0x4D, 0x4D, 0x0, 0x2A])) {
                return {
                    ext: 'tif',
                    mime: 'image/tiff'
                };
            }

            if (check([0x42, 0x4D])) {
                return {
                    ext: 'bmp',
                    mime: 'image/bmp'
                };
            }

            if (check([0x49, 0x49, 0xBC])) {
                return {
                    ext: 'jxr',
                    mime: 'image/vnd.ms-photo'
                };
            }

            if (check([0x38, 0x42, 0x50, 0x53])) {
                return {
                    ext: 'psd',
                    mime: 'image/vnd.adobe.photoshop'
                };
            }

            // Needs to be before the `zip` check
            if (check([0x50, 0x4B, 0x3, 0x4]) && check([0x6D, 0x69, 0x6D, 0x65, 0x74, 0x79, 0x70, 0x65, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x65, 0x70, 0x75, 0x62, 0x2B, 0x7A, 0x69, 0x70], { offset: 30 })) {
                return {
                    ext: 'epub',
                    mime: 'application/epub+zip'
                };
            }

            // Needs to be before `zip` check
            // Assumes signed `.xpi` from addons.mozilla.org
            if (check([0x50, 0x4B, 0x3, 0x4]) && check([0x4D, 0x45, 0x54, 0x41, 0x2D, 0x49, 0x4E, 0x46, 0x2F, 0x6D, 0x6F, 0x7A, 0x69, 0x6C, 0x6C, 0x61, 0x2E, 0x72, 0x73, 0x61], { offset: 30 })) {
                return {
                    ext: 'xpi',
                    mime: 'application/x-xpinstall'
                };
            }

            if (check([0x50, 0x4B]) && (buf[2] === 0x3 || buf[2] === 0x5 || buf[2] === 0x7) && (buf[3] === 0x4 || buf[3] === 0x6 || buf[3] === 0x8)) {
                return {
                    ext: 'zip',
                    mime: 'application/zip'
                };
            }

            if (check([0x75, 0x73, 0x74, 0x61, 0x72], { offset: 257 })) {
                return {
                    ext: 'tar',
                    mime: 'application/x-tar'
                };
            }

            if (check([0x52, 0x61, 0x72, 0x21, 0x1A, 0x7]) && (buf[6] === 0x0 || buf[6] === 0x1)) {
                return {
                    ext: 'rar',
                    mime: 'application/x-rar-compressed'
                };
            }

            if (check([0x1F, 0x8B, 0x8])) {
                return {
                    ext: 'gz',
                    mime: 'application/gzip'
                };
            }

            if (check([0x42, 0x5A, 0x68])) {
                return {
                    ext: 'bz2',
                    mime: 'application/x-bzip2'
                };
            }

            if (check([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C])) {
                return {
                    ext: '7z',
                    mime: 'application/x-7z-compressed'
                };
            }

            if (check([0x78, 0x01])) {
                return {
                    ext: 'dmg',
                    mime: 'application/x-apple-diskimage'
                };
            }

            if (check([0x0, 0x0, 0x0]) && (buf[3] === 0x18 || buf[3] === 0x20) && check([0x66, 0x74, 0x79, 0x70], { offset: 4 }) || check([0x33, 0x67, 0x70, 0x35]) || check([0x0, 0x0, 0x0, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x6D, 0x70, 0x34, 0x32]) && check([0x6D, 0x70, 0x34, 0x31, 0x6D, 0x70, 0x34, 0x32, 0x69, 0x73, 0x6F, 0x6D], { offset: 16 }) || check([0x0, 0x0, 0x0, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D]) || check([0x0, 0x0, 0x0, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x6D, 0x70, 0x34, 0x32, 0x0, 0x0, 0x0, 0x0])) {
                return {
                    ext: 'mp4',
                    mime: 'video/mp4'
                };
            }

            if (check([0x0, 0x0, 0x0, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x56])) {
                return {
                    ext: 'm4v',
                    mime: 'video/x-m4v'
                };
            }

            if (check([0x4D, 0x54, 0x68, 0x64])) {
                return {
                    ext: 'mid',
                    mime: 'audio/midi'
                };
            }

            // https://github.com/threatstack/libmagic/blob/master/magic/Magdir/matroska
            if (check([0x1A, 0x45, 0xDF, 0xA3])) {
                var sliced = buf.subarray(4, 4 + 4096);
                var idPos = sliced.findIndex(function (el, i, arr) {
                    return arr[i] === 0x42 && arr[i + 1] === 0x82;
                });

                if (idPos >= 0) {
                    var docTypePos = idPos + 3;
                    var findDocType = function findDocType(type) {
                        return Array.from(type).every(function (c, i) {
                            return sliced[docTypePos + i] === c.charCodeAt(0);
                        });
                    };

                    if (findDocType('matroska')) {
                        return {
                            ext: 'mkv',
                            mime: 'video/x-matroska'
                        };
                    }

                    if (findDocType('webm')) {
                        return {
                            ext: 'webm',
                            mime: 'video/webm'
                        };
                    }
                }
            }

            if (check([0x0, 0x0, 0x0, 0x14, 0x66, 0x74, 0x79, 0x70, 0x71, 0x74, 0x20, 0x20]) || check([0x66, 0x72, 0x65, 0x65], { offset: 4 }) || check([0x66, 0x74, 0x79, 0x70, 0x71, 0x74, 0x20, 0x20], { offset: 4 }) || check([0x6D, 0x64, 0x61, 0x74], { offset: 4 }) || // MJPEG
                check([0x77, 0x69, 0x64, 0x65], { offset: 4 })) {
                return {
                    ext: 'mov',
                    mime: 'video/quicktime'
                };
            }

            if (check([0x52, 0x49, 0x46, 0x46]) && check([0x41, 0x56, 0x49], { offset: 8 })) {
                return {
                    ext: 'avi',
                    mime: 'video/x-msvideo'
                };
            }

            if (check([0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9])) {
                return {
                    ext: 'wmv',
                    mime: 'video/x-ms-wmv'
                };
            }

            if (check([0x0, 0x0, 0x1, 0xBA])) {
                return {
                    ext: 'mpg',
                    mime: 'video/mpeg'
                };
            }

            if (check([0x49, 0x44, 0x33]) || check([0xFF, 0xFB])) {
                return {
                    ext: 'mp3',
                    mime: 'audio/mpeg'
                };
            }

            if (check([0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41], { offset: 4 }) || check([0x4D, 0x34, 0x41, 0x20])) {
                return {
                    ext: 'm4a',
                    mime: 'audio/m4a'
                };
            }

            // Needs to be before `ogg` check
            if (check([0x4F, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64], { offset: 28 })) {
                return {
                    ext: 'opus',
                    mime: 'audio/opus'
                };
            }

            if (check([0x4F, 0x67, 0x67, 0x53])) {
                return {
                    ext: 'ogg',
                    mime: 'audio/ogg'
                };
            }

            if (check([0x66, 0x4C, 0x61, 0x43])) {
                return {
                    ext: 'flac',
                    mime: 'audio/x-flac'
                };
            }

            if (check([0x52, 0x49, 0x46, 0x46]) && check([0x57, 0x41, 0x56, 0x45], { offset: 8 })) {
                return {
                    ext: 'wav',
                    mime: 'audio/x-wav'
                };
            }

            if (check([0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A])) {
                return {
                    ext: 'amr',
                    mime: 'audio/amr'
                };
            }

            if (check([0x25, 0x50, 0x44, 0x46])) {
                return {
                    ext: 'pdf',
                    mime: 'application/pdf'
                };
            }

            if (check([0x4D, 0x5A])) {
                return {
                    ext: 'exe',
                    mime: 'application/x-msdownload'
                };
            }

            if ((buf[0] === 0x43 || buf[0] === 0x46) && check([0x57, 0x53], { offset: 1 })) {
                return {
                    ext: 'swf',
                    mime: 'application/x-shockwave-flash'
                };
            }

            if (check([0x7B, 0x5C, 0x72, 0x74, 0x66])) {
                return {
                    ext: 'rtf',
                    mime: 'application/rtf'
                };
            }

            if (check([0x00, 0x61, 0x73, 0x6D])) {
                return {
                    ext: 'wasm',
                    mime: 'application/wasm'
                };
            }

            if (check([0x77, 0x4F, 0x46, 0x46]) && (check([0x00, 0x01, 0x00, 0x00], { offset: 4 }) || check([0x4F, 0x54, 0x54, 0x4F], { offset: 4 }))) {
                return {
                    ext: 'woff',
                    mime: 'font/woff'
                };
            }

            if (check([0x77, 0x4F, 0x46, 0x32]) && (check([0x00, 0x01, 0x00, 0x00], { offset: 4 }) || check([0x4F, 0x54, 0x54, 0x4F], { offset: 4 }))) {
                return {
                    ext: 'woff2',
                    mime: 'font/woff2'
                };
            }

            if (check([0x4C, 0x50], { offset: 34 }) && (check([0x00, 0x00, 0x01], { offset: 8 }) || check([0x01, 0x00, 0x02], { offset: 8 }) || check([0x02, 0x00, 0x02], { offset: 8 }))) {
                return {
                    ext: 'eot',
                    mime: 'application/octet-stream'
                };
            }

            if (check([0x00, 0x01, 0x00, 0x00, 0x00])) {
                return {
                    ext: 'ttf',
                    mime: 'font/ttf'
                };
            }

            if (check([0x4F, 0x54, 0x54, 0x4F, 0x00])) {
                return {
                    ext: 'otf',
                    mime: 'font/otf'
                };
            }

            if (check([0x00, 0x00, 0x01, 0x00])) {
                return {
                    ext: 'ico',
                    mime: 'image/x-icon'
                };
            }

            if (check([0x46, 0x4C, 0x56, 0x01])) {
                return {
                    ext: 'flv',
                    mime: 'video/x-flv'
                };
            }

            if (check([0x25, 0x21])) {
                return {
                    ext: 'ps',
                    mime: 'application/postscript'
                };
            }

            if (check([0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00])) {
                return {
                    ext: 'xz',
                    mime: 'application/x-xz'
                };
            }

            if (check([0x53, 0x51, 0x4C, 0x69])) {
                return {
                    ext: 'sqlite',
                    mime: 'application/x-sqlite3'
                };
            }

            if (check([0x4E, 0x45, 0x53, 0x1A])) {
                return {
                    ext: 'nes',
                    mime: 'application/x-nintendo-nes-rom'
                };
            }

            if (check([0x43, 0x72, 0x32, 0x34])) {
                return {
                    ext: 'crx',
                    mime: 'application/x-google-chrome-extension'
                };
            }

            if (check([0x4D, 0x53, 0x43, 0x46]) || check([0x49, 0x53, 0x63, 0x28])) {
                return {
                    ext: 'cab',
                    mime: 'application/vnd.ms-cab-compressed'
                };
            }

            // Needs to be before `ar` check
            if (check([0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E, 0x0A, 0x64, 0x65, 0x62, 0x69, 0x61, 0x6E, 0x2D, 0x62, 0x69, 0x6E, 0x61, 0x72, 0x79])) {
                return {
                    ext: 'deb',
                    mime: 'application/x-deb'
                };
            }

            if (check([0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E])) {
                return {
                    ext: 'ar',
                    mime: 'application/x-unix-archive'
                };
            }

            if (check([0xED, 0xAB, 0xEE, 0xDB])) {
                return {
                    ext: 'rpm',
                    mime: 'application/x-rpm'
                };
            }

            if (check([0x1F, 0xA0]) || check([0x1F, 0x9D])) {
                return {
                    ext: 'Z',
                    mime: 'application/x-compress'
                };
            }

            if (check([0x4C, 0x5A, 0x49, 0x50])) {
                return {
                    ext: 'lz',
                    mime: 'application/x-lzip'
                };
            }

            if (check([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1])) {
                return {
                    ext: 'msi',
                    mime: 'application/x-msi'
                };
            }

            if (check([0x06, 0x0E, 0x2B, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0D, 0x01, 0x02, 0x01, 0x01, 0x02])) {
                return {
                    ext: 'mxf',
                    mime: 'application/mxf'
                };
            }

            if (check([0x47], { offset: 4 }) && (check([0x47], { offset: 192 }) || check([0x47], { offset: 196 }))) {
                return {
                    ext: 'mts',
                    mime: 'video/mp2t'
                };
            }

            if (check([0x42, 0x4C, 0x45, 0x4E, 0x44, 0x45, 0x52])) {
                return {
                    ext: 'blend',
                    mime: 'application/x-blender'
                };
            }

            if (check([0x42, 0x50, 0x47, 0xFB])) {
                return {
                    ext: 'bpg',
                    mime: 'image/bpg'
                };
            }

            return null;
        };

    },{}]},{},[79])(79)
});
//# sourceMappingURL=uppy.js.map