]> git.openstreetmap.org Git - rails.git/blobdiff - vendor/assets/iD/iD/mapillary-js/mapillary.js
Merge remote-tracking branch 'upstream/pull/2471'
[rails.git] / vendor / assets / iD / iD / mapillary-js / mapillary.js
index 6cf84f91dc6389125bb9f5a19a10cafe70420782..78087cb383a59d9c2a46b8236897753c0c232dd8 100644 (file)
@@ -156,7 +156,7 @@ function getSegDistSq(px, py, a, b) {
     return dx * dx + dy * dy;
 }
 
-},{"tinyqueue":227}],2:[function(require,module,exports){
+},{"tinyqueue":243}],2:[function(require,module,exports){
 /*
  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
  *
@@ -5604,6 +5604,6822 @@ if (typeof module != 'undefined' && module.exports) module.exports = Geohash; //
 
 
 },{}],23:[function(require,module,exports){
+// Top level file is just a mixin of submodules & constants
+'use strict';
+
+var assign    = require('./lib/utils/common').assign;
+
+var deflate   = require('./lib/deflate');
+var inflate   = require('./lib/inflate');
+var constants = require('./lib/zlib/constants');
+
+var pako = {};
+
+assign(pako, deflate, inflate, constants);
+
+module.exports = pako;
+
+},{"./lib/deflate":24,"./lib/inflate":25,"./lib/utils/common":26,"./lib/zlib/constants":29}],24:[function(require,module,exports){
+'use strict';
+
+
+var zlib_deflate = require('./zlib/deflate');
+var utils        = require('./utils/common');
+var strings      = require('./utils/strings');
+var msg          = require('./zlib/messages');
+var ZStream      = require('./zlib/zstream');
+
+var toString = Object.prototype.toString;
+
+/* Public constants ==========================================================*/
+/* ===========================================================================*/
+
+var Z_NO_FLUSH      = 0;
+var Z_FINISH        = 4;
+
+var Z_OK            = 0;
+var Z_STREAM_END    = 1;
+var Z_SYNC_FLUSH    = 2;
+
+var Z_DEFAULT_COMPRESSION = -1;
+
+var Z_DEFAULT_STRATEGY    = 0;
+
+var Z_DEFLATED  = 8;
+
+/* ===========================================================================*/
+
+
+/**
+ * class Deflate
+ *
+ * Generic JS-style wrapper for zlib calls. If you don't need
+ * streaming behaviour - use more simple functions: [[deflate]],
+ * [[deflateRaw]] and [[gzip]].
+ **/
+
+/* internal
+ * Deflate.chunks -> Array
+ *
+ * Chunks of output data, if [[Deflate#onData]] not overridden.
+ **/
+
+/**
+ * Deflate.result -> Uint8Array|Array
+ *
+ * Compressed result, generated by default [[Deflate#onData]]
+ * and [[Deflate#onEnd]] handlers. Filled after you push last chunk
+ * (call [[Deflate#push]] with `Z_FINISH` / `true` param)  or if you
+ * push a chunk with explicit flush (call [[Deflate#push]] with
+ * `Z_SYNC_FLUSH` param).
+ **/
+
+/**
+ * Deflate.err -> Number
+ *
+ * Error code after deflate finished. 0 (Z_OK) on success.
+ * You will not need it in real life, because deflate errors
+ * are possible only on wrong options or bad `onData` / `onEnd`
+ * custom handlers.
+ **/
+
+/**
+ * Deflate.msg -> String
+ *
+ * Error message, if [[Deflate.err]] != 0
+ **/
+
+
+/**
+ * new Deflate(options)
+ * - options (Object): zlib deflate options.
+ *
+ * Creates new deflator instance with specified params. Throws exception
+ * on bad params. Supported options:
+ *
+ * - `level`
+ * - `windowBits`
+ * - `memLevel`
+ * - `strategy`
+ * - `dictionary`
+ *
+ * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
+ * for more information on these.
+ *
+ * Additional options, for internal needs:
+ *
+ * - `chunkSize` - size of generated data chunks (16K by default)
+ * - `raw` (Boolean) - do raw deflate
+ * - `gzip` (Boolean) - create gzip wrapper
+ * - `to` (String) - if equal to 'string', then result will be "binary string"
+ *    (each char code [0..255])
+ * - `header` (Object) - custom header for gzip
+ *   - `text` (Boolean) - true if compressed data believed to be text
+ *   - `time` (Number) - modification time, unix timestamp
+ *   - `os` (Number) - operation system code
+ *   - `extra` (Array) - array of bytes with extra data (max 65536)
+ *   - `name` (String) - file name (binary string)
+ *   - `comment` (String) - comment (binary string)
+ *   - `hcrc` (Boolean) - true if header crc should be added
+ *
+ * ##### Example:
+ *
+ * ```javascript
+ * var pako = require('pako')
+ *   , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
+ *   , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
+ *
+ * var deflate = new pako.Deflate({ level: 3});
+ *
+ * deflate.push(chunk1, false);
+ * deflate.push(chunk2, true);  // true -> last chunk
+ *
+ * if (deflate.err) { throw new Error(deflate.err); }
+ *
+ * console.log(deflate.result);
+ * ```
+ **/
+function Deflate(options) {
+  if (!(this instanceof Deflate)) return new Deflate(options);
+
+  this.options = utils.assign({
+    level: Z_DEFAULT_COMPRESSION,
+    method: Z_DEFLATED,
+    chunkSize: 16384,
+    windowBits: 15,
+    memLevel: 8,
+    strategy: Z_DEFAULT_STRATEGY,
+    to: ''
+  }, options || {});
+
+  var opt = this.options;
+
+  if (opt.raw && (opt.windowBits > 0)) {
+    opt.windowBits = -opt.windowBits;
+  }
+
+  else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {
+    opt.windowBits += 16;
+  }
+
+  this.err    = 0;      // error code, if happens (0 = Z_OK)
+  this.msg    = '';     // error message
+  this.ended  = false;  // used to avoid multiple onEnd() calls
+  this.chunks = [];     // chunks of compressed data
+
+  this.strm = new ZStream();
+  this.strm.avail_out = 0;
+
+  var status = zlib_deflate.deflateInit2(
+    this.strm,
+    opt.level,
+    opt.method,
+    opt.windowBits,
+    opt.memLevel,
+    opt.strategy
+  );
+
+  if (status !== Z_OK) {
+    throw new Error(msg[status]);
+  }
+
+  if (opt.header) {
+    zlib_deflate.deflateSetHeader(this.strm, opt.header);
+  }
+
+  if (opt.dictionary) {
+    var dict;
+    // Convert data if needed
+    if (typeof opt.dictionary === 'string') {
+      // If we need to compress text, change encoding to utf8.
+      dict = strings.string2buf(opt.dictionary);
+    } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {
+      dict = new Uint8Array(opt.dictionary);
+    } else {
+      dict = opt.dictionary;
+    }
+
+    status = zlib_deflate.deflateSetDictionary(this.strm, dict);
+
+    if (status !== Z_OK) {
+      throw new Error(msg[status]);
+    }
+
+    this._dict_set = true;
+  }
+}
+
+/**
+ * Deflate#push(data[, mode]) -> Boolean
+ * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be
+ *   converted to utf8 byte sequence.
+ * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
+ *   See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.
+ *
+ * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
+ * new compressed chunks. Returns `true` on success. The last data block must have
+ * mode Z_FINISH (or `true`). That will flush internal pending buffers and call
+ * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you
+ * can use mode Z_SYNC_FLUSH, keeping the compression context.
+ *
+ * On fail call [[Deflate#onEnd]] with error code and return false.
+ *
+ * We strongly recommend to use `Uint8Array` on input for best speed (output
+ * array format is detected automatically). Also, don't skip last param and always
+ * use the same type in your code (boolean or number). That will improve JS speed.
+ *
+ * For regular `Array`-s make sure all elements are [0..255].
+ *
+ * ##### Example
+ *
+ * ```javascript
+ * push(chunk, false); // push one of data chunks
+ * ...
+ * push(chunk, true);  // push last chunk
+ * ```
+ **/
+Deflate.prototype.push = function (data, mode) {
+  var strm = this.strm;
+  var chunkSize = this.options.chunkSize;
+  var status, _mode;
+
+  if (this.ended) { return false; }
+
+  _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH);
+
+  // Convert data if needed
+  if (typeof data === 'string') {
+    // If we need to compress text, change encoding to utf8.
+    strm.input = strings.string2buf(data);
+  } else if (toString.call(data) === '[object ArrayBuffer]') {
+    strm.input = new Uint8Array(data);
+  } else {
+    strm.input = data;
+  }
+
+  strm.next_in = 0;
+  strm.avail_in = strm.input.length;
+
+  do {
+    if (strm.avail_out === 0) {
+      strm.output = new utils.Buf8(chunkSize);
+      strm.next_out = 0;
+      strm.avail_out = chunkSize;
+    }
+    status = zlib_deflate.deflate(strm, _mode);    /* no bad return value */
+
+    if (status !== Z_STREAM_END && status !== Z_OK) {
+      this.onEnd(status);
+      this.ended = true;
+      return false;
+    }
+    if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) {
+      if (this.options.to === 'string') {
+        this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out)));
+      } else {
+        this.onData(utils.shrinkBuf(strm.output, strm.next_out));
+      }
+    }
+  } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END);
+
+  // Finalize on the last chunk.
+  if (_mode === Z_FINISH) {
+    status = zlib_deflate.deflateEnd(this.strm);
+    this.onEnd(status);
+    this.ended = true;
+    return status === Z_OK;
+  }
+
+  // callback interim results if Z_SYNC_FLUSH.
+  if (_mode === Z_SYNC_FLUSH) {
+    this.onEnd(Z_OK);
+    strm.avail_out = 0;
+    return true;
+  }
+
+  return true;
+};
+
+
+/**
+ * Deflate#onData(chunk) -> Void
+ * - chunk (Uint8Array|Array|String): output data. Type of array depends
+ *   on js engine support. When string output requested, each chunk
+ *   will be string.
+ *
+ * By default, stores data blocks in `chunks[]` property and glue
+ * those in `onEnd`. Override this handler, if you need another behaviour.
+ **/
+Deflate.prototype.onData = function (chunk) {
+  this.chunks.push(chunk);
+};
+
+
+/**
+ * Deflate#onEnd(status) -> Void
+ * - status (Number): deflate status. 0 (Z_OK) on success,
+ *   other if not.
+ *
+ * Called once after you tell deflate that the input stream is
+ * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH)
+ * or if an error happened. By default - join collected chunks,
+ * free memory and fill `results` / `err` properties.
+ **/
+Deflate.prototype.onEnd = function (status) {
+  // On success - join
+  if (status === Z_OK) {
+    if (this.options.to === 'string') {
+      this.result = this.chunks.join('');
+    } else {
+      this.result = utils.flattenChunks(this.chunks);
+    }
+  }
+  this.chunks = [];
+  this.err = status;
+  this.msg = this.strm.msg;
+};
+
+
+/**
+ * deflate(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to compress.
+ * - options (Object): zlib deflate options.
+ *
+ * Compress `data` with deflate algorithm and `options`.
+ *
+ * Supported options are:
+ *
+ * - level
+ * - windowBits
+ * - memLevel
+ * - strategy
+ * - dictionary
+ *
+ * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
+ * for more information on these.
+ *
+ * Sugar (options):
+ *
+ * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
+ *   negative windowBits implicitly.
+ * - `to` (String) - if equal to 'string', then result will be "binary string"
+ *    (each char code [0..255])
+ *
+ * ##### Example:
+ *
+ * ```javascript
+ * var pako = require('pako')
+ *   , data = Uint8Array([1,2,3,4,5,6,7,8,9]);
+ *
+ * console.log(pako.deflate(data));
+ * ```
+ **/
+function deflate(input, options) {
+  var deflator = new Deflate(options);
+
+  deflator.push(input, true);
+
+  // That will never happens, if you don't cheat with options :)
+  if (deflator.err) { throw deflator.msg || msg[deflator.err]; }
+
+  return deflator.result;
+}
+
+
+/**
+ * deflateRaw(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to compress.
+ * - options (Object): zlib deflate options.
+ *
+ * The same as [[deflate]], but creates raw data, without wrapper
+ * (header and adler32 crc).
+ **/
+function deflateRaw(input, options) {
+  options = options || {};
+  options.raw = true;
+  return deflate(input, options);
+}
+
+
+/**
+ * gzip(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to compress.
+ * - options (Object): zlib deflate options.
+ *
+ * The same as [[deflate]], but create gzip wrapper instead of
+ * deflate one.
+ **/
+function gzip(input, options) {
+  options = options || {};
+  options.gzip = true;
+  return deflate(input, options);
+}
+
+
+exports.Deflate = Deflate;
+exports.deflate = deflate;
+exports.deflateRaw = deflateRaw;
+exports.gzip = gzip;
+
+},{"./utils/common":26,"./utils/strings":27,"./zlib/deflate":31,"./zlib/messages":36,"./zlib/zstream":38}],25:[function(require,module,exports){
+'use strict';
+
+
+var zlib_inflate = require('./zlib/inflate');
+var utils        = require('./utils/common');
+var strings      = require('./utils/strings');
+var c            = require('./zlib/constants');
+var msg          = require('./zlib/messages');
+var ZStream      = require('./zlib/zstream');
+var GZheader     = require('./zlib/gzheader');
+
+var toString = Object.prototype.toString;
+
+/**
+ * class Inflate
+ *
+ * Generic JS-style wrapper for zlib calls. If you don't need
+ * streaming behaviour - use more simple functions: [[inflate]]
+ * and [[inflateRaw]].
+ **/
+
+/* internal
+ * inflate.chunks -> Array
+ *
+ * Chunks of output data, if [[Inflate#onData]] not overridden.
+ **/
+
+/**
+ * Inflate.result -> Uint8Array|Array|String
+ *
+ * Uncompressed result, generated by default [[Inflate#onData]]
+ * and [[Inflate#onEnd]] handlers. Filled after you push last chunk
+ * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you
+ * push a chunk with explicit flush (call [[Inflate#push]] with
+ * `Z_SYNC_FLUSH` param).
+ **/
+
+/**
+ * Inflate.err -> Number
+ *
+ * Error code after inflate finished. 0 (Z_OK) on success.
+ * Should be checked if broken data possible.
+ **/
+
+/**
+ * Inflate.msg -> String
+ *
+ * Error message, if [[Inflate.err]] != 0
+ **/
+
+
+/**
+ * new Inflate(options)
+ * - options (Object): zlib inflate options.
+ *
+ * Creates new inflator instance with specified params. Throws exception
+ * on bad params. Supported options:
+ *
+ * - `windowBits`
+ * - `dictionary`
+ *
+ * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
+ * for more information on these.
+ *
+ * Additional options, for internal needs:
+ *
+ * - `chunkSize` - size of generated data chunks (16K by default)
+ * - `raw` (Boolean) - do raw inflate
+ * - `to` (String) - if equal to 'string', then result will be converted
+ *   from utf8 to utf16 (javascript) string. When string output requested,
+ *   chunk length can differ from `chunkSize`, depending on content.
+ *
+ * By default, when no options set, autodetect deflate/gzip data format via
+ * wrapper header.
+ *
+ * ##### Example:
+ *
+ * ```javascript
+ * var pako = require('pako')
+ *   , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
+ *   , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
+ *
+ * var inflate = new pako.Inflate({ level: 3});
+ *
+ * inflate.push(chunk1, false);
+ * inflate.push(chunk2, true);  // true -> last chunk
+ *
+ * if (inflate.err) { throw new Error(inflate.err); }
+ *
+ * console.log(inflate.result);
+ * ```
+ **/
+function Inflate(options) {
+  if (!(this instanceof Inflate)) return new Inflate(options);
+
+  this.options = utils.assign({
+    chunkSize: 16384,
+    windowBits: 0,
+    to: ''
+  }, options || {});
+
+  var opt = this.options;
+
+  // Force window size for `raw` data, if not set directly,
+  // because we have no header for autodetect.
+  if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {
+    opt.windowBits = -opt.windowBits;
+    if (opt.windowBits === 0) { opt.windowBits = -15; }
+  }
+
+  // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate
+  if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&
+      !(options && options.windowBits)) {
+    opt.windowBits += 32;
+  }
+
+  // Gzip header has no info about windows size, we can do autodetect only
+  // for deflate. So, if window size not set, force it to max when gzip possible
+  if ((opt.windowBits > 15) && (opt.windowBits < 48)) {
+    // bit 3 (16) -> gzipped data
+    // bit 4 (32) -> autodetect gzip/deflate
+    if ((opt.windowBits & 15) === 0) {
+      opt.windowBits |= 15;
+    }
+  }
+
+  this.err    = 0;      // error code, if happens (0 = Z_OK)
+  this.msg    = '';     // error message
+  this.ended  = false;  // used to avoid multiple onEnd() calls
+  this.chunks = [];     // chunks of compressed data
+
+  this.strm   = new ZStream();
+  this.strm.avail_out = 0;
+
+  var status  = zlib_inflate.inflateInit2(
+    this.strm,
+    opt.windowBits
+  );
+
+  if (status !== c.Z_OK) {
+    throw new Error(msg[status]);
+  }
+
+  this.header = new GZheader();
+
+  zlib_inflate.inflateGetHeader(this.strm, this.header);
+
+  // Setup dictionary
+  if (opt.dictionary) {
+    // Convert data if needed
+    if (typeof opt.dictionary === 'string') {
+      opt.dictionary = strings.string2buf(opt.dictionary);
+    } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {
+      opt.dictionary = new Uint8Array(opt.dictionary);
+    }
+    if (opt.raw) { //In raw mode we need to set the dictionary early
+      status = zlib_inflate.inflateSetDictionary(this.strm, opt.dictionary);
+      if (status !== c.Z_OK) {
+        throw new Error(msg[status]);
+      }
+    }
+  }
+}
+
+/**
+ * Inflate#push(data[, mode]) -> Boolean
+ * - data (Uint8Array|Array|ArrayBuffer|String): input data
+ * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
+ *   See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.
+ *
+ * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
+ * new output chunks. Returns `true` on success. The last data block must have
+ * mode Z_FINISH (or `true`). That will flush internal pending buffers and call
+ * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you
+ * can use mode Z_SYNC_FLUSH, keeping the decompression context.
+ *
+ * On fail call [[Inflate#onEnd]] with error code and return false.
+ *
+ * We strongly recommend to use `Uint8Array` on input for best speed (output
+ * format is detected automatically). Also, don't skip last param and always
+ * use the same type in your code (boolean or number). That will improve JS speed.
+ *
+ * For regular `Array`-s make sure all elements are [0..255].
+ *
+ * ##### Example
+ *
+ * ```javascript
+ * push(chunk, false); // push one of data chunks
+ * ...
+ * push(chunk, true);  // push last chunk
+ * ```
+ **/
+Inflate.prototype.push = function (data, mode) {
+  var strm = this.strm;
+  var chunkSize = this.options.chunkSize;
+  var dictionary = this.options.dictionary;
+  var status, _mode;
+  var next_out_utf8, tail, utf8str;
+
+  // Flag to properly process Z_BUF_ERROR on testing inflate call
+  // when we check that all output data was flushed.
+  var allowBufError = false;
+
+  if (this.ended) { return false; }
+  _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH);
+
+  // Convert data if needed
+  if (typeof data === 'string') {
+    // Only binary strings can be decompressed on practice
+    strm.input = strings.binstring2buf(data);
+  } else if (toString.call(data) === '[object ArrayBuffer]') {
+    strm.input = new Uint8Array(data);
+  } else {
+    strm.input = data;
+  }
+
+  strm.next_in = 0;
+  strm.avail_in = strm.input.length;
+
+  do {
+    if (strm.avail_out === 0) {
+      strm.output = new utils.Buf8(chunkSize);
+      strm.next_out = 0;
+      strm.avail_out = chunkSize;
+    }
+
+    status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH);    /* no bad return value */
+
+    if (status === c.Z_NEED_DICT && dictionary) {
+      status = zlib_inflate.inflateSetDictionary(this.strm, dictionary);
+    }
+
+    if (status === c.Z_BUF_ERROR && allowBufError === true) {
+      status = c.Z_OK;
+      allowBufError = false;
+    }
+
+    if (status !== c.Z_STREAM_END && status !== c.Z_OK) {
+      this.onEnd(status);
+      this.ended = true;
+      return false;
+    }
+
+    if (strm.next_out) {
+      if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && (_mode === c.Z_FINISH || _mode === c.Z_SYNC_FLUSH))) {
+
+        if (this.options.to === 'string') {
+
+          next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
+
+          tail = strm.next_out - next_out_utf8;
+          utf8str = strings.buf2string(strm.output, next_out_utf8);
+
+          // move tail
+          strm.next_out = tail;
+          strm.avail_out = chunkSize - tail;
+          if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); }
+
+          this.onData(utf8str);
+
+        } else {
+          this.onData(utils.shrinkBuf(strm.output, strm.next_out));
+        }
+      }
+    }
+
+    // When no more input data, we should check that internal inflate buffers
+    // are flushed. The only way to do it when avail_out = 0 - run one more
+    // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR.
+    // Here we set flag to process this error properly.
+    //
+    // NOTE. Deflate does not return error in this case and does not needs such
+    // logic.
+    if (strm.avail_in === 0 && strm.avail_out === 0) {
+      allowBufError = true;
+    }
+
+  } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== c.Z_STREAM_END);
+
+  if (status === c.Z_STREAM_END) {
+    _mode = c.Z_FINISH;
+  }
+
+  // Finalize on the last chunk.
+  if (_mode === c.Z_FINISH) {
+    status = zlib_inflate.inflateEnd(this.strm);
+    this.onEnd(status);
+    this.ended = true;
+    return status === c.Z_OK;
+  }
+
+  // callback interim results if Z_SYNC_FLUSH.
+  if (_mode === c.Z_SYNC_FLUSH) {
+    this.onEnd(c.Z_OK);
+    strm.avail_out = 0;
+    return true;
+  }
+
+  return true;
+};
+
+
+/**
+ * Inflate#onData(chunk) -> Void
+ * - chunk (Uint8Array|Array|String): output data. Type of array depends
+ *   on js engine support. When string output requested, each chunk
+ *   will be string.
+ *
+ * By default, stores data blocks in `chunks[]` property and glue
+ * those in `onEnd`. Override this handler, if you need another behaviour.
+ **/
+Inflate.prototype.onData = function (chunk) {
+  this.chunks.push(chunk);
+};
+
+
+/**
+ * Inflate#onEnd(status) -> Void
+ * - status (Number): inflate status. 0 (Z_OK) on success,
+ *   other if not.
+ *
+ * Called either after you tell inflate that the input stream is
+ * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH)
+ * or if an error happened. By default - join collected chunks,
+ * free memory and fill `results` / `err` properties.
+ **/
+Inflate.prototype.onEnd = function (status) {
+  // On success - join
+  if (status === c.Z_OK) {
+    if (this.options.to === 'string') {
+      // Glue & convert here, until we teach pako to send
+      // utf8 aligned strings to onData
+      this.result = this.chunks.join('');
+    } else {
+      this.result = utils.flattenChunks(this.chunks);
+    }
+  }
+  this.chunks = [];
+  this.err = status;
+  this.msg = this.strm.msg;
+};
+
+
+/**
+ * inflate(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to decompress.
+ * - options (Object): zlib inflate options.
+ *
+ * Decompress `data` with inflate/ungzip and `options`. Autodetect
+ * format via wrapper header by default. That's why we don't provide
+ * separate `ungzip` method.
+ *
+ * Supported options are:
+ *
+ * - windowBits
+ *
+ * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
+ * for more information.
+ *
+ * Sugar (options):
+ *
+ * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
+ *   negative windowBits implicitly.
+ * - `to` (String) - if equal to 'string', then result will be converted
+ *   from utf8 to utf16 (javascript) string. When string output requested,
+ *   chunk length can differ from `chunkSize`, depending on content.
+ *
+ *
+ * ##### Example:
+ *
+ * ```javascript
+ * var pako = require('pako')
+ *   , input = pako.deflate([1,2,3,4,5,6,7,8,9])
+ *   , output;
+ *
+ * try {
+ *   output = pako.inflate(input);
+ * } catch (err)
+ *   console.log(err);
+ * }
+ * ```
+ **/
+function inflate(input, options) {
+  var inflator = new Inflate(options);
+
+  inflator.push(input, true);
+
+  // That will never happens, if you don't cheat with options :)
+  if (inflator.err) { throw inflator.msg || msg[inflator.err]; }
+
+  return inflator.result;
+}
+
+
+/**
+ * inflateRaw(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to decompress.
+ * - options (Object): zlib inflate options.
+ *
+ * The same as [[inflate]], but creates raw data, without wrapper
+ * (header and adler32 crc).
+ **/
+function inflateRaw(input, options) {
+  options = options || {};
+  options.raw = true;
+  return inflate(input, options);
+}
+
+
+/**
+ * ungzip(data[, options]) -> Uint8Array|Array|String
+ * - data (Uint8Array|Array|String): input data to decompress.
+ * - options (Object): zlib inflate options.
+ *
+ * Just shortcut to [[inflate]], because it autodetects format
+ * by header.content. Done for convenience.
+ **/
+
+
+exports.Inflate = Inflate;
+exports.inflate = inflate;
+exports.inflateRaw = inflateRaw;
+exports.ungzip  = inflate;
+
+},{"./utils/common":26,"./utils/strings":27,"./zlib/constants":29,"./zlib/gzheader":32,"./zlib/inflate":34,"./zlib/messages":36,"./zlib/zstream":38}],26:[function(require,module,exports){
+'use strict';
+
+
+var TYPED_OK =  (typeof Uint8Array !== 'undefined') &&
+                (typeof Uint16Array !== 'undefined') &&
+                (typeof Int32Array !== 'undefined');
+
+function _has(obj, key) {
+  return Object.prototype.hasOwnProperty.call(obj, key);
+}
+
+exports.assign = function (obj /*from1, from2, from3, ...*/) {
+  var sources = Array.prototype.slice.call(arguments, 1);
+  while (sources.length) {
+    var source = sources.shift();
+    if (!source) { continue; }
+
+    if (typeof source !== 'object') {
+      throw new TypeError(source + 'must be non-object');
+    }
+
+    for (var p in source) {
+      if (_has(source, p)) {
+        obj[p] = source[p];
+      }
+    }
+  }
+
+  return obj;
+};
+
+
+// reduce buffer size, avoiding mem copy
+exports.shrinkBuf = function (buf, size) {
+  if (buf.length === size) { return buf; }
+  if (buf.subarray) { return buf.subarray(0, size); }
+  buf.length = size;
+  return buf;
+};
+
+
+var fnTyped = {
+  arraySet: function (dest, src, src_offs, len, dest_offs) {
+    if (src.subarray && dest.subarray) {
+      dest.set(src.subarray(src_offs, src_offs + len), dest_offs);
+      return;
+    }
+    // Fallback to ordinary array
+    for (var i = 0; i < len; i++) {
+      dest[dest_offs + i] = src[src_offs + i];
+    }
+  },
+  // Join array of chunks to single array.
+  flattenChunks: function (chunks) {
+    var i, l, len, pos, chunk, result;
+
+    // calculate data length
+    len = 0;
+    for (i = 0, l = chunks.length; i < l; i++) {
+      len += chunks[i].length;
+    }
+
+    // join chunks
+    result = new Uint8Array(len);
+    pos = 0;
+    for (i = 0, l = chunks.length; i < l; i++) {
+      chunk = chunks[i];
+      result.set(chunk, pos);
+      pos += chunk.length;
+    }
+
+    return result;
+  }
+};
+
+var fnUntyped = {
+  arraySet: function (dest, src, src_offs, len, dest_offs) {
+    for (var i = 0; i < len; i++) {
+      dest[dest_offs + i] = src[src_offs + i];
+    }
+  },
+  // Join array of chunks to single array.
+  flattenChunks: function (chunks) {
+    return [].concat.apply([], chunks);
+  }
+};
+
+
+// Enable/Disable typed arrays use, for testing
+//
+exports.setTyped = function (on) {
+  if (on) {
+    exports.Buf8  = Uint8Array;
+    exports.Buf16 = Uint16Array;
+    exports.Buf32 = Int32Array;
+    exports.assign(exports, fnTyped);
+  } else {
+    exports.Buf8  = Array;
+    exports.Buf16 = Array;
+    exports.Buf32 = Array;
+    exports.assign(exports, fnUntyped);
+  }
+};
+
+exports.setTyped(TYPED_OK);
+
+},{}],27:[function(require,module,exports){
+// String encode/decode helpers
+'use strict';
+
+
+var utils = require('./common');
+
+
+// Quick check if we can use fast array to bin string conversion
+//
+// - apply(Array) can fail on Android 2.2
+// - apply(Uint8Array) can fail on iOS 5.1 Safari
+//
+var STR_APPLY_OK = true;
+var STR_APPLY_UIA_OK = true;
+
+try { String.fromCharCode.apply(null, [ 0 ]); } catch (__) { STR_APPLY_OK = false; }
+try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }
+
+
+// Table with utf8 lengths (calculated by first byte of sequence)
+// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
+// because max possible codepoint is 0x10ffff
+var _utf8len = new utils.Buf8(256);
+for (var q = 0; q < 256; q++) {
+  _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
+}
+_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start
+
+
+// convert string to array (typed, when possible)
+exports.string2buf = function (str) {
+  var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
+
+  // count binary size
+  for (m_pos = 0; m_pos < str_len; m_pos++) {
+    c = str.charCodeAt(m_pos);
+    if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
+      c2 = str.charCodeAt(m_pos + 1);
+      if ((c2 & 0xfc00) === 0xdc00) {
+        c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
+        m_pos++;
+      }
+    }
+    buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
+  }
+
+  // allocate buffer
+  buf = new utils.Buf8(buf_len);
+
+  // convert
+  for (i = 0, m_pos = 0; i < buf_len; m_pos++) {
+    c = str.charCodeAt(m_pos);
+    if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
+      c2 = str.charCodeAt(m_pos + 1);
+      if ((c2 & 0xfc00) === 0xdc00) {
+        c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
+        m_pos++;
+      }
+    }
+    if (c < 0x80) {
+      /* one byte */
+      buf[i++] = c;
+    } else if (c < 0x800) {
+      /* two bytes */
+      buf[i++] = 0xC0 | (c >>> 6);
+      buf[i++] = 0x80 | (c & 0x3f);
+    } else if (c < 0x10000) {
+      /* three bytes */
+      buf[i++] = 0xE0 | (c >>> 12);
+      buf[i++] = 0x80 | (c >>> 6 & 0x3f);
+      buf[i++] = 0x80 | (c & 0x3f);
+    } else {
+      /* four bytes */
+      buf[i++] = 0xf0 | (c >>> 18);
+      buf[i++] = 0x80 | (c >>> 12 & 0x3f);
+      buf[i++] = 0x80 | (c >>> 6 & 0x3f);
+      buf[i++] = 0x80 | (c & 0x3f);
+    }
+  }
+
+  return buf;
+};
+
+// Helper (used in 2 places)
+function buf2binstring(buf, len) {
+  // On Chrome, the arguments in a function call that are allowed is `65534`.
+  // If the length of the buffer is smaller than that, we can use this optimization,
+  // otherwise we will take a slower path.
+  if (len < 65534) {
+    if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) {
+      return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len));
+    }
+  }
+
+  var result = '';
+  for (var i = 0; i < len; i++) {
+    result += String.fromCharCode(buf[i]);
+  }
+  return result;
+}
+
+
+// Convert byte array to binary string
+exports.buf2binstring = function (buf) {
+  return buf2binstring(buf, buf.length);
+};
+
+
+// Convert binary string (typed, when possible)
+exports.binstring2buf = function (str) {
+  var buf = new utils.Buf8(str.length);
+  for (var i = 0, len = buf.length; i < len; i++) {
+    buf[i] = str.charCodeAt(i);
+  }
+  return buf;
+};
+
+
+// convert array to string
+exports.buf2string = function (buf, max) {
+  var i, out, c, c_len;
+  var len = max || buf.length;
+
+  // Reserve max possible length (2 words per char)
+  // NB: by unknown reasons, Array is significantly faster for
+  //     String.fromCharCode.apply than Uint16Array.
+  var utf16buf = new Array(len * 2);
+
+  for (out = 0, i = 0; i < len;) {
+    c = buf[i++];
+    // quick process ascii
+    if (c < 0x80) { utf16buf[out++] = c; continue; }
+
+    c_len = _utf8len[c];
+    // skip 5 & 6 byte codes
+    if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }
+
+    // apply mask on first byte
+    c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
+    // join the rest
+    while (c_len > 1 && i < len) {
+      c = (c << 6) | (buf[i++] & 0x3f);
+      c_len--;
+    }
+
+    // terminated by end of string?
+    if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
+
+    if (c < 0x10000) {
+      utf16buf[out++] = c;
+    } else {
+      c -= 0x10000;
+      utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
+      utf16buf[out++] = 0xdc00 | (c & 0x3ff);
+    }
+  }
+
+  return buf2binstring(utf16buf, out);
+};
+
+
+// Calculate max possible position in utf8 buffer,
+// that will not break sequence. If that's not possible
+// - (very small limits) return max size as is.
+//
+// buf[] - utf8 bytes array
+// max   - length limit (mandatory);
+exports.utf8border = function (buf, max) {
+  var pos;
+
+  max = max || buf.length;
+  if (max > buf.length) { max = buf.length; }
+
+  // go back from last position, until start of sequence found
+  pos = max - 1;
+  while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
+
+  // Very small and broken sequence,
+  // return max, because we should return something anyway.
+  if (pos < 0) { return max; }
+
+  // If we came to start of buffer - that means buffer is too small,
+  // return max too.
+  if (pos === 0) { return max; }
+
+  return (pos + _utf8len[buf[pos]] > max) ? pos : max;
+};
+
+},{"./common":26}],28:[function(require,module,exports){
+'use strict';
+
+// Note: adler32 takes 12% for level 0 and 2% for level 6.
+// It isn't worth it to make additional optimizations as in original.
+// Small size is preferable.
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+function adler32(adler, buf, len, pos) {
+  var s1 = (adler & 0xffff) |0,
+      s2 = ((adler >>> 16) & 0xffff) |0,
+      n = 0;
+
+  while (len !== 0) {
+    // Set limit ~ twice less than 5552, to keep
+    // s2 in 31-bits, because we force signed ints.
+    // in other case %= will fail.
+    n = len > 2000 ? 2000 : len;
+    len -= n;
+
+    do {
+      s1 = (s1 + buf[pos++]) |0;
+      s2 = (s2 + s1) |0;
+    } while (--n);
+
+    s1 %= 65521;
+    s2 %= 65521;
+  }
+
+  return (s1 | (s2 << 16)) |0;
+}
+
+
+module.exports = adler32;
+
+},{}],29:[function(require,module,exports){
+'use strict';
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+module.exports = {
+
+  /* Allowed flush values; see deflate() and inflate() below for details */
+  Z_NO_FLUSH:         0,
+  Z_PARTIAL_FLUSH:    1,
+  Z_SYNC_FLUSH:       2,
+  Z_FULL_FLUSH:       3,
+  Z_FINISH:           4,
+  Z_BLOCK:            5,
+  Z_TREES:            6,
+
+  /* Return codes for the compression/decompression functions. Negative values
+  * are errors, positive values are used for special but normal events.
+  */
+  Z_OK:               0,
+  Z_STREAM_END:       1,
+  Z_NEED_DICT:        2,
+  Z_ERRNO:           -1,
+  Z_STREAM_ERROR:    -2,
+  Z_DATA_ERROR:      -3,
+  //Z_MEM_ERROR:     -4,
+  Z_BUF_ERROR:       -5,
+  //Z_VERSION_ERROR: -6,
+
+  /* compression levels */
+  Z_NO_COMPRESSION:         0,
+  Z_BEST_SPEED:             1,
+  Z_BEST_COMPRESSION:       9,
+  Z_DEFAULT_COMPRESSION:   -1,
+
+
+  Z_FILTERED:               1,
+  Z_HUFFMAN_ONLY:           2,
+  Z_RLE:                    3,
+  Z_FIXED:                  4,
+  Z_DEFAULT_STRATEGY:       0,
+
+  /* Possible values of the data_type field (though see inflate()) */
+  Z_BINARY:                 0,
+  Z_TEXT:                   1,
+  //Z_ASCII:                1, // = Z_TEXT (deprecated)
+  Z_UNKNOWN:                2,
+
+  /* The deflate compression method */
+  Z_DEFLATED:               8
+  //Z_NULL:                 null // Use -1 or null inline, depending on var type
+};
+
+},{}],30:[function(require,module,exports){
+'use strict';
+
+// Note: we can't get significant speed boost here.
+// So write code to minimize size - no pregenerated tables
+// and array tools dependencies.
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+// Use ordinary array, since untyped makes no boost here
+function makeTable() {
+  var c, table = [];
+
+  for (var n = 0; n < 256; n++) {
+    c = n;
+    for (var k = 0; k < 8; k++) {
+      c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
+    }
+    table[n] = c;
+  }
+
+  return table;
+}
+
+// Create table on load. Just 255 signed longs. Not a problem.
+var crcTable = makeTable();
+
+
+function crc32(crc, buf, len, pos) {
+  var t = crcTable,
+      end = pos + len;
+
+  crc ^= -1;
+
+  for (var i = pos; i < end; i++) {
+    crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
+  }
+
+  return (crc ^ (-1)); // >>> 0;
+}
+
+
+module.exports = crc32;
+
+},{}],31:[function(require,module,exports){
+'use strict';
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+var utils   = require('../utils/common');
+var trees   = require('./trees');
+var adler32 = require('./adler32');
+var crc32   = require('./crc32');
+var msg     = require('./messages');
+
+/* Public constants ==========================================================*/
+/* ===========================================================================*/
+
+
+/* Allowed flush values; see deflate() and inflate() below for details */
+var Z_NO_FLUSH      = 0;
+var Z_PARTIAL_FLUSH = 1;
+//var Z_SYNC_FLUSH    = 2;
+var Z_FULL_FLUSH    = 3;
+var Z_FINISH        = 4;
+var Z_BLOCK         = 5;
+//var Z_TREES         = 6;
+
+
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+var Z_OK            = 0;
+var Z_STREAM_END    = 1;
+//var Z_NEED_DICT     = 2;
+//var Z_ERRNO         = -1;
+var Z_STREAM_ERROR  = -2;
+var Z_DATA_ERROR    = -3;
+//var Z_MEM_ERROR     = -4;
+var Z_BUF_ERROR     = -5;
+//var Z_VERSION_ERROR = -6;
+
+
+/* compression levels */
+//var Z_NO_COMPRESSION      = 0;
+//var Z_BEST_SPEED          = 1;
+//var Z_BEST_COMPRESSION    = 9;
+var Z_DEFAULT_COMPRESSION = -1;
+
+
+var Z_FILTERED            = 1;
+var Z_HUFFMAN_ONLY        = 2;
+var Z_RLE                 = 3;
+var Z_FIXED               = 4;
+var Z_DEFAULT_STRATEGY    = 0;
+
+/* Possible values of the data_type field (though see inflate()) */
+//var Z_BINARY              = 0;
+//var Z_TEXT                = 1;
+//var Z_ASCII               = 1; // = Z_TEXT
+var Z_UNKNOWN             = 2;
+
+
+/* The deflate compression method */
+var Z_DEFLATED  = 8;
+
+/*============================================================================*/
+
+
+var MAX_MEM_LEVEL = 9;
+/* Maximum value for memLevel in deflateInit2 */
+var MAX_WBITS = 15;
+/* 32K LZ77 window */
+var DEF_MEM_LEVEL = 8;
+
+
+var LENGTH_CODES  = 29;
+/* number of length codes, not counting the special END_BLOCK code */
+var LITERALS      = 256;
+/* number of literal bytes 0..255 */
+var L_CODES       = LITERALS + 1 + LENGTH_CODES;
+/* number of Literal or Length codes, including the END_BLOCK code */
+var D_CODES       = 30;
+/* number of distance codes */
+var BL_CODES      = 19;
+/* number of codes used to transfer the bit lengths */
+var HEAP_SIZE     = 2 * L_CODES + 1;
+/* maximum heap size */
+var MAX_BITS  = 15;
+/* All codes must not exceed MAX_BITS bits */
+
+var MIN_MATCH = 3;
+var MAX_MATCH = 258;
+var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+var PRESET_DICT = 0x20;
+
+var INIT_STATE = 42;
+var EXTRA_STATE = 69;
+var NAME_STATE = 73;
+var COMMENT_STATE = 91;
+var HCRC_STATE = 103;
+var BUSY_STATE = 113;
+var FINISH_STATE = 666;
+
+var BS_NEED_MORE      = 1; /* block not completed, need more input or more output */
+var BS_BLOCK_DONE     = 2; /* block flush performed */
+var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
+var BS_FINISH_DONE    = 4; /* finish done, accept no more input or output */
+
+var OS_CODE = 0x03; // Unix :) . Don't detect, use this default.
+
+function err(strm, errorCode) {
+  strm.msg = msg[errorCode];
+  return errorCode;
+}
+
+function rank(f) {
+  return ((f) << 1) - ((f) > 4 ? 9 : 0);
+}
+
+function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }
+
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->output buffer and copying into it.
+ * (See also read_buf()).
+ */
+function flush_pending(strm) {
+  var s = strm.state;
+
+  //_tr_flush_bits(s);
+  var len = s.pending;
+  if (len > strm.avail_out) {
+    len = strm.avail_out;
+  }
+  if (len === 0) { return; }
+
+  utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out);
+  strm.next_out += len;
+  s.pending_out += len;
+  strm.total_out += len;
+  strm.avail_out -= len;
+  s.pending -= len;
+  if (s.pending === 0) {
+    s.pending_out = 0;
+  }
+}
+
+
+function flush_block_only(s, last) {
+  trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);
+  s.block_start = s.strstart;
+  flush_pending(s.strm);
+}
+
+
+function put_byte(s, b) {
+  s.pending_buf[s.pending++] = b;
+}
+
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+function putShortMSB(s, b) {
+//  put_byte(s, (Byte)(b >> 8));
+//  put_byte(s, (Byte)(b & 0xff));
+  s.pending_buf[s.pending++] = (b >>> 8) & 0xff;
+  s.pending_buf[s.pending++] = b & 0xff;
+}
+
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read.  All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->input buffer and copying from it.
+ * (See also flush_pending()).
+ */
+function read_buf(strm, buf, start, size) {
+  var len = strm.avail_in;
+
+  if (len > size) { len = size; }
+  if (len === 0) { return 0; }
+
+  strm.avail_in -= len;
+
+  // zmemcpy(buf, strm->next_in, len);
+  utils.arraySet(buf, strm.input, strm.next_in, len, start);
+  if (strm.state.wrap === 1) {
+    strm.adler = adler32(strm.adler, buf, len, start);
+  }
+
+  else if (strm.state.wrap === 2) {
+    strm.adler = crc32(strm.adler, buf, len, start);
+  }
+
+  strm.next_in += len;
+  strm.total_in += len;
+
+  return len;
+}
+
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+function longest_match(s, cur_match) {
+  var chain_length = s.max_chain_length;      /* max hash chain length */
+  var scan = s.strstart; /* current string */
+  var match;                       /* matched string */
+  var len;                           /* length of current match */
+  var best_len = s.prev_length;              /* best match length so far */
+  var nice_match = s.nice_match;             /* stop if match long enough */
+  var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?
+      s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;
+
+  var _win = s.window; // shortcut
+
+  var wmask = s.w_mask;
+  var prev  = s.prev;
+
+  /* Stop when cur_match becomes <= limit. To simplify the code,
+   * we prevent matches with the string of window index 0.
+   */
+
+  var strend = s.strstart + MAX_MATCH;
+  var scan_end1  = _win[scan + best_len - 1];
+  var scan_end   = _win[scan + best_len];
+
+  /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+   * It is easy to get rid of this optimization if necessary.
+   */
+  // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+  /* Do not waste too much time if we already have a good match: */
+  if (s.prev_length >= s.good_match) {
+    chain_length >>= 2;
+  }
+  /* Do not look for matches beyond the end of the input. This is necessary
+   * to make deflate deterministic.
+   */
+  if (nice_match > s.lookahead) { nice_match = s.lookahead; }
+
+  // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+  do {
+    // Assert(cur_match < s->strstart, "no future");
+    match = cur_match;
+
+    /* Skip to next match if the match length cannot increase
+     * or if the match length is less than 2.  Note that the checks below
+     * for insufficient lookahead only occur occasionally for performance
+     * reasons.  Therefore uninitialized memory will be accessed, and
+     * conditional jumps will be made that depend on those values.
+     * However the length of the match is limited to the lookahead, so
+     * the output of deflate is not affected by the uninitialized values.
+     */
+
+    if (_win[match + best_len]     !== scan_end  ||
+        _win[match + best_len - 1] !== scan_end1 ||
+        _win[match]                !== _win[scan] ||
+        _win[++match]              !== _win[scan + 1]) {
+      continue;
+    }
+
+    /* The check at best_len-1 can be removed because it will be made
+     * again later. (This heuristic is not always a win.)
+     * It is not necessary to compare scan[2] and match[2] since they
+     * are always equal when the other bytes match, given that
+     * the hash keys are equal and that HASH_BITS >= 8.
+     */
+    scan += 2;
+    match++;
+    // Assert(*scan == *match, "match[2]?");
+
+    /* We check for insufficient lookahead only every 8th comparison;
+     * the 256th check will be made at strstart+258.
+     */
+    do {
+      /*jshint noempty:false*/
+    } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
+             _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
+             _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
+             _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
+             scan < strend);
+
+    // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+    len = MAX_MATCH - (strend - scan);
+    scan = strend - MAX_MATCH;
+
+    if (len > best_len) {
+      s.match_start = cur_match;
+      best_len = len;
+      if (len >= nice_match) {
+        break;
+      }
+      scan_end1  = _win[scan + best_len - 1];
+      scan_end   = _win[scan + best_len];
+    }
+  } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);
+
+  if (best_len <= s.lookahead) {
+    return best_len;
+  }
+  return s.lookahead;
+}
+
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ *    At least one byte has been read, or avail_in == 0; reads are
+ *    performed for at least two bytes (required for the zip translate_eol
+ *    option -- not supported here).
+ */
+function fill_window(s) {
+  var _w_size = s.w_size;
+  var p, n, m, more, str;
+
+  //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
+
+  do {
+    more = s.window_size - s.lookahead - s.strstart;
+
+    // JS ints have 32 bit, block below not needed
+    /* Deal with !@#$% 64K limit: */
+    //if (sizeof(int) <= 2) {
+    //    if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+    //        more = wsize;
+    //
+    //  } else if (more == (unsigned)(-1)) {
+    //        /* Very unlikely, but possible on 16 bit machine if
+    //         * strstart == 0 && lookahead == 1 (input done a byte at time)
+    //         */
+    //        more--;
+    //    }
+    //}
+
+
+    /* If the window is almost full and there is insufficient lookahead,
+     * move the upper half to the lower one to make room in the upper half.
+     */
+    if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {
+
+      utils.arraySet(s.window, s.window, _w_size, _w_size, 0);
+      s.match_start -= _w_size;
+      s.strstart -= _w_size;
+      /* we now have strstart >= MAX_DIST */
+      s.block_start -= _w_size;
+
+      /* Slide the hash table (could be avoided with 32 bit values
+       at the expense of memory usage). We slide even when level == 0
+       to keep the hash table consistent if we switch back to level > 0
+       later. (Using level 0 permanently is not an optimal usage of
+       zlib, so we don't care about this pathological case.)
+       */
+
+      n = s.hash_size;
+      p = n;
+      do {
+        m = s.head[--p];
+        s.head[p] = (m >= _w_size ? m - _w_size : 0);
+      } while (--n);
+
+      n = _w_size;
+      p = n;
+      do {
+        m = s.prev[--p];
+        s.prev[p] = (m >= _w_size ? m - _w_size : 0);
+        /* If n is not on any hash chain, prev[n] is garbage but
+         * its value will never be used.
+         */
+      } while (--n);
+
+      more += _w_size;
+    }
+    if (s.strm.avail_in === 0) {
+      break;
+    }
+
+    /* If there was no sliding:
+     *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+     *    more == window_size - lookahead - strstart
+     * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+     * => more >= window_size - 2*WSIZE + 2
+     * In the BIG_MEM or MMAP case (not yet supported),
+     *   window_size == input_size + MIN_LOOKAHEAD  &&
+     *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+     * Otherwise, window_size == 2*WSIZE so more >= 2.
+     * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+     */
+    //Assert(more >= 2, "more < 2");
+    n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);
+    s.lookahead += n;
+
+    /* Initialize the hash value now that we have some input: */
+    if (s.lookahead + s.insert >= MIN_MATCH) {
+      str = s.strstart - s.insert;
+      s.ins_h = s.window[str];
+
+      /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */
+      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask;
+//#if MIN_MATCH != 3
+//        Call update_hash() MIN_MATCH-3 more times
+//#endif
+      while (s.insert) {
+        /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
+        s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask;
+
+        s.prev[str & s.w_mask] = s.head[s.ins_h];
+        s.head[s.ins_h] = str;
+        str++;
+        s.insert--;
+        if (s.lookahead + s.insert < MIN_MATCH) {
+          break;
+        }
+      }
+    }
+    /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+     * but this is not important since only literal bytes will be emitted.
+     */
+
+  } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);
+
+  /* If the WIN_INIT bytes after the end of the current data have never been
+   * written, then zero those bytes in order to avoid memory check reports of
+   * the use of uninitialized (or uninitialised as Julian writes) bytes by
+   * the longest match routines.  Update the high water mark for the next
+   * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
+   * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+   */
+//  if (s.high_water < s.window_size) {
+//    var curr = s.strstart + s.lookahead;
+//    var init = 0;
+//
+//    if (s.high_water < curr) {
+//      /* Previous high water mark below current data -- zero WIN_INIT
+//       * bytes or up to end of window, whichever is less.
+//       */
+//      init = s.window_size - curr;
+//      if (init > WIN_INIT)
+//        init = WIN_INIT;
+//      zmemzero(s->window + curr, (unsigned)init);
+//      s->high_water = curr + init;
+//    }
+//    else if (s->high_water < (ulg)curr + WIN_INIT) {
+//      /* High water mark at or above current data, but below current data
+//       * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+//       * to end of window, whichever is less.
+//       */
+//      init = (ulg)curr + WIN_INIT - s->high_water;
+//      if (init > s->window_size - s->high_water)
+//        init = s->window_size - s->high_water;
+//      zmemzero(s->window + s->high_water, (unsigned)init);
+//      s->high_water += init;
+//    }
+//  }
+//
+//  Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+//    "not enough room for search");
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+function deflate_stored(s, flush) {
+  /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+   * to pending_buf_size, and each stored block has a 5 byte header:
+   */
+  var max_block_size = 0xffff;
+
+  if (max_block_size > s.pending_buf_size - 5) {
+    max_block_size = s.pending_buf_size - 5;
+  }
+
+  /* Copy as much as possible from input to output: */
+  for (;;) {
+    /* Fill the window as much as possible: */
+    if (s.lookahead <= 1) {
+
+      //Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+      //  s->block_start >= (long)s->w_size, "slide too late");
+//      if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) ||
+//        s.block_start >= s.w_size)) {
+//        throw  new Error("slide too late");
+//      }
+
+      fill_window(s);
+      if (s.lookahead === 0 && flush === Z_NO_FLUSH) {
+        return BS_NEED_MORE;
+      }
+
+      if (s.lookahead === 0) {
+        break;
+      }
+      /* flush the current block */
+    }
+    //Assert(s->block_start >= 0L, "block gone");
+//    if (s.block_start < 0) throw new Error("block gone");
+
+    s.strstart += s.lookahead;
+    s.lookahead = 0;
+
+    /* Emit a stored block if pending_buf will be full: */
+    var max_start = s.block_start + max_block_size;
+
+    if (s.strstart === 0 || s.strstart >= max_start) {
+      /* strstart == 0 is possible when wraparound on 16-bit machine */
+      s.lookahead = s.strstart - max_start;
+      s.strstart = max_start;
+      /*** FLUSH_BLOCK(s, 0); ***/
+      flush_block_only(s, false);
+      if (s.strm.avail_out === 0) {
+        return BS_NEED_MORE;
+      }
+      /***/
+
+
+    }
+    /* Flush if we may have to slide, otherwise block_start may become
+     * negative and the data will be gone:
+     */
+    if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) {
+      /*** FLUSH_BLOCK(s, 0); ***/
+      flush_block_only(s, false);
+      if (s.strm.avail_out === 0) {
+        return BS_NEED_MORE;
+      }
+      /***/
+    }
+  }
+
+  s.insert = 0;
+
+  if (flush === Z_FINISH) {
+    /*** FLUSH_BLOCK(s, 1); ***/
+    flush_block_only(s, true);
+    if (s.strm.avail_out === 0) {
+      return BS_FINISH_STARTED;
+    }
+    /***/
+    return BS_FINISH_DONE;
+  }
+
+  if (s.strstart > s.block_start) {
+    /*** FLUSH_BLOCK(s, 0); ***/
+    flush_block_only(s, false);
+    if (s.strm.avail_out === 0) {
+      return BS_NEED_MORE;
+    }
+    /***/
+  }
+
+  return BS_NEED_MORE;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+function deflate_fast(s, flush) {
+  var hash_head;        /* head of the hash chain */
+  var bflush;           /* set if current block must be flushed */
+
+  for (;;) {
+    /* Make sure that we always have enough lookahead, except
+     * at the end of the input file. We need MAX_MATCH bytes
+     * for the next match, plus MIN_MATCH bytes to insert the
+     * string following the next match.
+     */
+    if (s.lookahead < MIN_LOOKAHEAD) {
+      fill_window(s);
+      if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
+        return BS_NEED_MORE;
+      }
+      if (s.lookahead === 0) {
+        break; /* flush the current block */
+      }
+    }
+
+    /* Insert the string window[strstart .. strstart+2] in the
+     * dictionary, and set hash_head to the head of the hash chain:
+     */
+    hash_head = 0/*NIL*/;
+    if (s.lookahead >= MIN_MATCH) {
+      /*** INSERT_STRING(s, s.strstart, hash_head); ***/
+      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
+      hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
+      s.head[s.ins_h] = s.strstart;
+      /***/
+    }
+
+    /* Find the longest match, discarding those <= prev_length.
+     * At this point we have always match_length < MIN_MATCH
+     */
+    if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {
+      /* To simplify the code, we prevent matches with the string
+       * of window index 0 (in particular we have to avoid a match
+       * of the string with itself at the start of the input file).
+       */
+      s.match_length = longest_match(s, hash_head);
+      /* longest_match() sets match_start */
+    }
+    if (s.match_length >= MIN_MATCH) {
+      // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only
+
+      /*** _tr_tally_dist(s, s.strstart - s.match_start,
+                     s.match_length - MIN_MATCH, bflush); ***/
+      bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH);
+
+      s.lookahead -= s.match_length;
+
+      /* Insert new strings in the hash table only if the match length
+       * is not too large. This saves time but degrades compression.
+       */
+      if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) {
+        s.match_length--; /* string at strstart already in table */
+        do {
+          s.strstart++;
+          /*** INSERT_STRING(s, s.strstart, hash_head); ***/
+          s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
+          hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
+          s.head[s.ins_h] = s.strstart;
+          /***/
+          /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+           * always MIN_MATCH bytes ahead.
+           */
+        } while (--s.match_length !== 0);
+        s.strstart++;
+      } else
+      {
+        s.strstart += s.match_length;
+        s.match_length = 0;
+        s.ins_h = s.window[s.strstart];
+        /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */
+        s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask;
+
+//#if MIN_MATCH != 3
+//                Call UPDATE_HASH() MIN_MATCH-3 more times
+//#endif
+        /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+         * matter since it will be recomputed at next deflate call.
+         */
+      }
+    } else {
+      /* No match, output a literal byte */
+      //Tracevv((stderr,"%c", s.window[s.strstart]));
+      /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
+      bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
+
+      s.lookahead--;
+      s.strstart++;
+    }
+    if (bflush) {
+      /*** FLUSH_BLOCK(s, 0); ***/
+      flush_block_only(s, false);
+      if (s.strm.avail_out === 0) {
+        return BS_NEED_MORE;
+      }
+      /***/
+    }
+  }
+  s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1);
+  if (flush === Z_FINISH) {
+    /*** FLUSH_BLOCK(s, 1); ***/
+    flush_block_only(s, true);
+    if (s.strm.avail_out === 0) {
+      return BS_FINISH_STARTED;
+    }
+    /***/
+    return BS_FINISH_DONE;
+  }
+  if (s.last_lit) {
+    /*** FLUSH_BLOCK(s, 0); ***/
+    flush_block_only(s, false);
+    if (s.strm.avail_out === 0) {
+      return BS_NEED_MORE;
+    }
+    /***/
+  }
+  return BS_BLOCK_DONE;
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+function deflate_slow(s, flush) {
+  var hash_head;          /* head of hash chain */
+  var bflush;              /* set if current block must be flushed */
+
+  var max_insert;
+
+  /* Process the input block. */
+  for (;;) {
+    /* Make sure that we always have enough lookahead, except
+     * at the end of the input file. We need MAX_MATCH bytes
+     * for the next match, plus MIN_MATCH bytes to insert the
+     * string following the next match.
+     */
+    if (s.lookahead < MIN_LOOKAHEAD) {
+      fill_window(s);
+      if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
+        return BS_NEED_MORE;
+      }
+      if (s.lookahead === 0) { break; } /* flush the current block */
+    }
+
+    /* Insert the string window[strstart .. strstart+2] in the
+     * dictionary, and set hash_head to the head of the hash chain:
+     */
+    hash_head = 0/*NIL*/;
+    if (s.lookahead >= MIN_MATCH) {
+      /*** INSERT_STRING(s, s.strstart, hash_head); ***/
+      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
+      hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
+      s.head[s.ins_h] = s.strstart;
+      /***/
+    }
+
+    /* Find the longest match, discarding those <= prev_length.
+     */
+    s.prev_length = s.match_length;
+    s.prev_match = s.match_start;
+    s.match_length = MIN_MATCH - 1;
+
+    if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&
+        s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {
+      /* To simplify the code, we prevent matches with the string
+       * of window index 0 (in particular we have to avoid a match
+       * of the string with itself at the start of the input file).
+       */
+      s.match_length = longest_match(s, hash_head);
+      /* longest_match() sets match_start */
+
+      if (s.match_length <= 5 &&
+         (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {
+
+        /* If prev_match is also MIN_MATCH, match_start is garbage
+         * but we will ignore the current match anyway.
+         */
+        s.match_length = MIN_MATCH - 1;
+      }
+    }
+    /* If there was a match at the previous step and the current
+     * match is not better, output the previous match:
+     */
+    if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) {
+      max_insert = s.strstart + s.lookahead - MIN_MATCH;
+      /* Do not insert strings in hash table beyond this. */
+
+      //check_match(s, s.strstart-1, s.prev_match, s.prev_length);
+
+      /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,
+                     s.prev_length - MIN_MATCH, bflush);***/
+      bflush = trees._tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH);
+      /* Insert in hash table all strings up to the end of the match.
+       * strstart-1 and strstart are already inserted. If there is not
+       * enough lookahead, the last two strings are not inserted in
+       * the hash table.
+       */
+      s.lookahead -= s.prev_length - 1;
+      s.prev_length -= 2;
+      do {
+        if (++s.strstart <= max_insert) {
+          /*** INSERT_STRING(s, s.strstart, hash_head); ***/
+          s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
+          hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
+          s.head[s.ins_h] = s.strstart;
+          /***/
+        }
+      } while (--s.prev_length !== 0);
+      s.match_available = 0;
+      s.match_length = MIN_MATCH - 1;
+      s.strstart++;
+
+      if (bflush) {
+        /*** FLUSH_BLOCK(s, 0); ***/
+        flush_block_only(s, false);
+        if (s.strm.avail_out === 0) {
+          return BS_NEED_MORE;
+        }
+        /***/
+      }
+
+    } else if (s.match_available) {
+      /* If there was no match at the previous position, output a
+       * single literal. If there was a match but the current match
+       * is longer, truncate the previous match to a single literal.
+       */
+      //Tracevv((stderr,"%c", s->window[s->strstart-1]));
+      /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
+      bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]);
+
+      if (bflush) {
+        /*** FLUSH_BLOCK_ONLY(s, 0) ***/
+        flush_block_only(s, false);
+        /***/
+      }
+      s.strstart++;
+      s.lookahead--;
+      if (s.strm.avail_out === 0) {
+        return BS_NEED_MORE;
+      }
+    } else {
+      /* There is no previous match to compare with, wait for
+       * the next step to decide.
+       */
+      s.match_available = 1;
+      s.strstart++;
+      s.lookahead--;
+    }
+  }
+  //Assert (flush != Z_NO_FLUSH, "no flush?");
+  if (s.match_available) {
+    //Tracevv((stderr,"%c", s->window[s->strstart-1]));
+    /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
+    bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]);
+
+    s.match_available = 0;
+  }
+  s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1;
+  if (flush === Z_FINISH) {
+    /*** FLUSH_BLOCK(s, 1); ***/
+    flush_block_only(s, true);
+    if (s.strm.avail_out === 0) {
+      return BS_FINISH_STARTED;
+    }
+    /***/
+    return BS_FINISH_DONE;
+  }
+  if (s.last_lit) {
+    /*** FLUSH_BLOCK(s, 0); ***/
+    flush_block_only(s, false);
+    if (s.strm.avail_out === 0) {
+      return BS_NEED_MORE;
+    }
+    /***/
+  }
+
+  return BS_BLOCK_DONE;
+}
+
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one.  Do not maintain a hash table.  (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+function deflate_rle(s, flush) {
+  var bflush;            /* set if current block must be flushed */
+  var prev;              /* byte at distance one to match */
+  var scan, strend;      /* scan goes up to strend for length of run */
+
+  var _win = s.window;
+
+  for (;;) {
+    /* Make sure that we always have enough lookahead, except
+     * at the end of the input file. We need MAX_MATCH bytes
+     * for the longest run, plus one for the unrolled loop.
+     */
+    if (s.lookahead <= MAX_MATCH) {
+      fill_window(s);
+      if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) {
+        return BS_NEED_MORE;
+      }
+      if (s.lookahead === 0) { break; } /* flush the current block */
+    }
+
+    /* See how many times the previous byte repeats */
+    s.match_length = 0;
+    if (s.lookahead >= MIN_MATCH && s.strstart > 0) {
+      scan = s.strstart - 1;
+      prev = _win[scan];
+      if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
+        strend = s.strstart + MAX_MATCH;
+        do {
+          /*jshint noempty:false*/
+        } while (prev === _win[++scan] && prev === _win[++scan] &&
+                 prev === _win[++scan] && prev === _win[++scan] &&
+                 prev === _win[++scan] && prev === _win[++scan] &&
+                 prev === _win[++scan] && prev === _win[++scan] &&
+                 scan < strend);
+        s.match_length = MAX_MATCH - (strend - scan);
+        if (s.match_length > s.lookahead) {
+          s.match_length = s.lookahead;
+        }
+      }
+      //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
+    }
+
+    /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+    if (s.match_length >= MIN_MATCH) {
+      //check_match(s, s.strstart, s.strstart - 1, s.match_length);
+
+      /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/
+      bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH);
+
+      s.lookahead -= s.match_length;
+      s.strstart += s.match_length;
+      s.match_length = 0;
+    } else {
+      /* No match, output a literal byte */
+      //Tracevv((stderr,"%c", s->window[s->strstart]));
+      /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
+      bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
+
+      s.lookahead--;
+      s.strstart++;
+    }
+    if (bflush) {
+      /*** FLUSH_BLOCK(s, 0); ***/
+      flush_block_only(s, false);
+      if (s.strm.avail_out === 0) {
+        return BS_NEED_MORE;
+      }
+      /***/
+    }
+  }
+  s.insert = 0;
+  if (flush === Z_FINISH) {
+    /*** FLUSH_BLOCK(s, 1); ***/
+    flush_block_only(s, true);
+    if (s.strm.avail_out === 0) {
+      return BS_FINISH_STARTED;
+    }
+    /***/
+    return BS_FINISH_DONE;
+  }
+  if (s.last_lit) {
+    /*** FLUSH_BLOCK(s, 0); ***/
+    flush_block_only(s, false);
+    if (s.strm.avail_out === 0) {
+      return BS_NEED_MORE;
+    }
+    /***/
+  }
+  return BS_BLOCK_DONE;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+function deflate_huff(s, flush) {
+  var bflush;             /* set if current block must be flushed */
+
+  for (;;) {
+    /* Make sure that we have a literal to write. */
+    if (s.lookahead === 0) {
+      fill_window(s);
+      if (s.lookahead === 0) {
+        if (flush === Z_NO_FLUSH) {
+          return BS_NEED_MORE;
+        }
+        break;      /* flush the current block */
+      }
+    }
+
+    /* Output a literal byte */
+    s.match_length = 0;
+    //Tracevv((stderr,"%c", s->window[s->strstart]));
+    /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
+    bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
+    s.lookahead--;
+    s.strstart++;
+    if (bflush) {
+      /*** FLUSH_BLOCK(s, 0); ***/
+      flush_block_only(s, false);
+      if (s.strm.avail_out === 0) {
+        return BS_NEED_MORE;
+      }
+      /***/
+    }
+  }
+  s.insert = 0;
+  if (flush === Z_FINISH) {
+    /*** FLUSH_BLOCK(s, 1); ***/
+    flush_block_only(s, true);
+    if (s.strm.avail_out === 0) {
+      return BS_FINISH_STARTED;
+    }
+    /***/
+    return BS_FINISH_DONE;
+  }
+  if (s.last_lit) {
+    /*** FLUSH_BLOCK(s, 0); ***/
+    flush_block_only(s, false);
+    if (s.strm.avail_out === 0) {
+      return BS_NEED_MORE;
+    }
+    /***/
+  }
+  return BS_BLOCK_DONE;
+}
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+function Config(good_length, max_lazy, nice_length, max_chain, func) {
+  this.good_length = good_length;
+  this.max_lazy = max_lazy;
+  this.nice_length = nice_length;
+  this.max_chain = max_chain;
+  this.func = func;
+}
+
+var configuration_table;
+
+configuration_table = [
+  /*      good lazy nice chain */
+  new Config(0, 0, 0, 0, deflate_stored),          /* 0 store only */
+  new Config(4, 4, 8, 4, deflate_fast),            /* 1 max speed, no lazy matches */
+  new Config(4, 5, 16, 8, deflate_fast),           /* 2 */
+  new Config(4, 6, 32, 32, deflate_fast),          /* 3 */
+
+  new Config(4, 4, 16, 16, deflate_slow),          /* 4 lazy matches */
+  new Config(8, 16, 32, 32, deflate_slow),         /* 5 */
+  new Config(8, 16, 128, 128, deflate_slow),       /* 6 */
+  new Config(8, 32, 128, 256, deflate_slow),       /* 7 */
+  new Config(32, 128, 258, 1024, deflate_slow),    /* 8 */
+  new Config(32, 258, 258, 4096, deflate_slow)     /* 9 max compression */
+];
+
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+function lm_init(s) {
+  s.window_size = 2 * s.w_size;
+
+  /*** CLEAR_HASH(s); ***/
+  zero(s.head); // Fill with NIL (= 0);
+
+  /* Set the default configuration parameters:
+   */
+  s.max_lazy_match = configuration_table[s.level].max_lazy;
+  s.good_match = configuration_table[s.level].good_length;
+  s.nice_match = configuration_table[s.level].nice_length;
+  s.max_chain_length = configuration_table[s.level].max_chain;
+
+  s.strstart = 0;
+  s.block_start = 0;
+  s.lookahead = 0;
+  s.insert = 0;
+  s.match_length = s.prev_length = MIN_MATCH - 1;
+  s.match_available = 0;
+  s.ins_h = 0;
+}
+
+
+function DeflateState() {
+  this.strm = null;            /* pointer back to this zlib stream */
+  this.status = 0;            /* as the name implies */
+  this.pending_buf = null;      /* output still pending */
+  this.pending_buf_size = 0;  /* size of pending_buf */
+  this.pending_out = 0;       /* next pending byte to output to the stream */
+  this.pending = 0;           /* nb of bytes in the pending buffer */
+  this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */
+  this.gzhead = null;         /* gzip header information to write */
+  this.gzindex = 0;           /* where in extra, name, or comment */
+  this.method = Z_DEFLATED; /* can only be DEFLATED */
+  this.last_flush = -1;   /* value of flush param for previous deflate call */
+
+  this.w_size = 0;  /* LZ77 window size (32K by default) */
+  this.w_bits = 0;  /* log2(w_size)  (8..16) */
+  this.w_mask = 0;  /* w_size - 1 */
+
+  this.window = null;
+  /* Sliding window. Input bytes are read into the second half of the window,
+   * and move to the first half later to keep a dictionary of at least wSize
+   * bytes. With this organization, matches are limited to a distance of
+   * wSize-MAX_MATCH bytes, but this ensures that IO is always
+   * performed with a length multiple of the block size.
+   */
+
+  this.window_size = 0;
+  /* Actual size of window: 2*wSize, except when the user input buffer
+   * is directly used as sliding window.
+   */
+
+  this.prev = null;
+  /* Link to older string with same hash index. To limit the size of this
+   * array to 64K, this link is maintained only for the last 32K strings.
+   * An index in this array is thus a window index modulo 32K.
+   */
+
+  this.head = null;   /* Heads of the hash chains or NIL. */
+
+  this.ins_h = 0;       /* hash index of string to be inserted */
+  this.hash_size = 0;   /* number of elements in hash table */
+  this.hash_bits = 0;   /* log2(hash_size) */
+  this.hash_mask = 0;   /* hash_size-1 */
+
+  this.hash_shift = 0;
+  /* Number of bits by which ins_h must be shifted at each input
+   * step. It must be such that after MIN_MATCH steps, the oldest
+   * byte no longer takes part in the hash key, that is:
+   *   hash_shift * MIN_MATCH >= hash_bits
+   */
+
+  this.block_start = 0;
+  /* Window position at the beginning of the current output block. Gets
+   * negative when the window is moved backwards.
+   */
+
+  this.match_length = 0;      /* length of best match */
+  this.prev_match = 0;        /* previous match */
+  this.match_available = 0;   /* set if previous match exists */
+  this.strstart = 0;          /* start of string to insert */
+  this.match_start = 0;       /* start of matching string */
+  this.lookahead = 0;         /* number of valid bytes ahead in window */
+
+  this.prev_length = 0;
+  /* Length of the best match at previous step. Matches not greater than this
+   * are discarded. This is used in the lazy match evaluation.
+   */
+
+  this.max_chain_length = 0;
+  /* To speed up deflation, hash chains are never searched beyond this
+   * length.  A higher limit improves compression ratio but degrades the
+   * speed.
+   */
+
+  this.max_lazy_match = 0;
+  /* Attempt to find a better match only when the current match is strictly
+   * smaller than this value. This mechanism is used only for compression
+   * levels >= 4.
+   */
+  // That's alias to max_lazy_match, don't use directly
+  //this.max_insert_length = 0;
+  /* Insert new strings in the hash table only if the match length is not
+   * greater than this length. This saves time but degrades compression.
+   * max_insert_length is used only for compression levels <= 3.
+   */
+
+  this.level = 0;     /* compression level (1..9) */
+  this.strategy = 0;  /* favor or force Huffman coding*/
+
+  this.good_match = 0;
+  /* Use a faster search when the previous match is longer than this */
+
+  this.nice_match = 0; /* Stop searching when current match exceeds this */
+
+              /* used by trees.c: */
+
+  /* Didn't use ct_data typedef below to suppress compiler warning */
+
+  // struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+  // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+  // struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+
+  // Use flat array of DOUBLE size, with interleaved fata,
+  // because JS does not support effective
+  this.dyn_ltree  = new utils.Buf16(HEAP_SIZE * 2);
+  this.dyn_dtree  = new utils.Buf16((2 * D_CODES + 1) * 2);
+  this.bl_tree    = new utils.Buf16((2 * BL_CODES + 1) * 2);
+  zero(this.dyn_ltree);
+  zero(this.dyn_dtree);
+  zero(this.bl_tree);
+
+  this.l_desc   = null;         /* desc. for literal tree */
+  this.d_desc   = null;         /* desc. for distance tree */
+  this.bl_desc  = null;         /* desc. for bit length tree */
+
+  //ush bl_count[MAX_BITS+1];
+  this.bl_count = new utils.Buf16(MAX_BITS + 1);
+  /* number of codes at each bit length for an optimal tree */
+
+  //int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */
+  this.heap = new utils.Buf16(2 * L_CODES + 1);  /* heap used to build the Huffman trees */
+  zero(this.heap);
+
+  this.heap_len = 0;               /* number of elements in the heap */
+  this.heap_max = 0;               /* element of largest frequency */
+  /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+   * The same heap array is used to build all trees.
+   */
+
+  this.depth = new utils.Buf16(2 * L_CODES + 1); //uch depth[2*L_CODES+1];
+  zero(this.depth);
+  /* Depth of each subtree used as tie breaker for trees of equal frequency
+   */
+
+  this.l_buf = 0;          /* buffer index for literals or lengths */
+
+  this.lit_bufsize = 0;
+  /* Size of match buffer for literals/lengths.  There are 4 reasons for
+   * limiting lit_bufsize to 64K:
+   *   - frequencies can be kept in 16 bit counters
+   *   - if compression is not successful for the first block, all input
+   *     data is still in the window so we can still emit a stored block even
+   *     when input comes from standard input.  (This can also be done for
+   *     all blocks if lit_bufsize is not greater than 32K.)
+   *   - if compression is not successful for a file smaller than 64K, we can
+   *     even emit a stored file instead of a stored block (saving 5 bytes).
+   *     This is applicable only for zip (not gzip or zlib).
+   *   - creating new Huffman trees less frequently may not provide fast
+   *     adaptation to changes in the input data statistics. (Take for
+   *     example a binary file with poorly compressible code followed by
+   *     a highly compressible string table.) Smaller buffer sizes give
+   *     fast adaptation but have of course the overhead of transmitting
+   *     trees more frequently.
+   *   - I can't count above 4
+   */
+
+  this.last_lit = 0;      /* running index in l_buf */
+
+  this.d_buf = 0;
+  /* Buffer index for distances. To simplify the code, d_buf and l_buf have
+   * the same number of elements. To use different lengths, an extra flag
+   * array would be necessary.
+   */
+
+  this.opt_len = 0;       /* bit length of current block with optimal trees */
+  this.static_len = 0;    /* bit length of current block with static trees */
+  this.matches = 0;       /* number of string matches in current block */
+  this.insert = 0;        /* bytes at end of window left to insert */
+
+
+  this.bi_buf = 0;
+  /* Output buffer. bits are inserted starting at the bottom (least
+   * significant bits).
+   */
+  this.bi_valid = 0;
+  /* Number of valid bits in bi_buf.  All bits above the last valid bit
+   * are always zero.
+   */
+
+  // Used for window memory init. We safely ignore it for JS. That makes
+  // sense only for pointers and memory check tools.
+  //this.high_water = 0;
+  /* High water mark offset in window for initialized bytes -- bytes above
+   * this are set to zero in order to avoid memory check warnings when
+   * longest match routines access bytes past the input.  This is then
+   * updated to the new high water mark.
+   */
+}
+
+
+function deflateResetKeep(strm) {
+  var s;
+
+  if (!strm || !strm.state) {
+    return err(strm, Z_STREAM_ERROR);
+  }
+
+  strm.total_in = strm.total_out = 0;
+  strm.data_type = Z_UNKNOWN;
+
+  s = strm.state;
+  s.pending = 0;
+  s.pending_out = 0;
+
+  if (s.wrap < 0) {
+    s.wrap = -s.wrap;
+    /* was made negative by deflate(..., Z_FINISH); */
+  }
+  s.status = (s.wrap ? INIT_STATE : BUSY_STATE);
+  strm.adler = (s.wrap === 2) ?
+    0  // crc32(0, Z_NULL, 0)
+  :
+    1; // adler32(0, Z_NULL, 0)
+  s.last_flush = Z_NO_FLUSH;
+  trees._tr_init(s);
+  return Z_OK;
+}
+
+
+function deflateReset(strm) {
+  var ret = deflateResetKeep(strm);
+  if (ret === Z_OK) {
+    lm_init(strm.state);
+  }
+  return ret;
+}
+
+
+function deflateSetHeader(strm, head) {
+  if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+  if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; }
+  strm.state.gzhead = head;
+  return Z_OK;
+}
+
+
+function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {
+  if (!strm) { // === Z_NULL
+    return Z_STREAM_ERROR;
+  }
+  var wrap = 1;
+
+  if (level === Z_DEFAULT_COMPRESSION) {
+    level = 6;
+  }
+
+  if (windowBits < 0) { /* suppress zlib wrapper */
+    wrap = 0;
+    windowBits = -windowBits;
+  }
+
+  else if (windowBits > 15) {
+    wrap = 2;           /* write gzip wrapper instead */
+    windowBits -= 16;
+  }
+
+
+  if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED ||
+    windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+    strategy < 0 || strategy > Z_FIXED) {
+    return err(strm, Z_STREAM_ERROR);
+  }
+
+
+  if (windowBits === 8) {
+    windowBits = 9;
+  }
+  /* until 256-byte window bug fixed */
+
+  var s = new DeflateState();
+
+  strm.state = s;
+  s.strm = strm;
+
+  s.wrap = wrap;
+  s.gzhead = null;
+  s.w_bits = windowBits;
+  s.w_size = 1 << s.w_bits;
+  s.w_mask = s.w_size - 1;
+
+  s.hash_bits = memLevel + 7;
+  s.hash_size = 1 << s.hash_bits;
+  s.hash_mask = s.hash_size - 1;
+  s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH);
+
+  s.window = new utils.Buf8(s.w_size * 2);
+  s.head = new utils.Buf16(s.hash_size);
+  s.prev = new utils.Buf16(s.w_size);
+
+  // Don't need mem init magic for JS.
+  //s.high_water = 0;  /* nothing written to s->window yet */
+
+  s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+  s.pending_buf_size = s.lit_bufsize * 4;
+
+  //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+  //s->pending_buf = (uchf *) overlay;
+  s.pending_buf = new utils.Buf8(s.pending_buf_size);
+
+  // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)
+  //s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+  s.d_buf = 1 * s.lit_bufsize;
+
+  //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+  s.l_buf = (1 + 2) * s.lit_bufsize;
+
+  s.level = level;
+  s.strategy = strategy;
+  s.method = method;
+
+  return deflateReset(strm);
+}
+
+function deflateInit(strm, level) {
+  return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+}
+
+
+function deflate(strm, flush) {
+  var old_flush, s;
+  var beg, val; // for gzip header write only
+
+  if (!strm || !strm.state ||
+    flush > Z_BLOCK || flush < 0) {
+    return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR;
+  }
+
+  s = strm.state;
+
+  if (!strm.output ||
+      (!strm.input && strm.avail_in !== 0) ||
+      (s.status === FINISH_STATE && flush !== Z_FINISH)) {
+    return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR);
+  }
+
+  s.strm = strm; /* just in case */
+  old_flush = s.last_flush;
+  s.last_flush = flush;
+
+  /* Write the header */
+  if (s.status === INIT_STATE) {
+
+    if (s.wrap === 2) { // GZIP header
+      strm.adler = 0;  //crc32(0L, Z_NULL, 0);
+      put_byte(s, 31);
+      put_byte(s, 139);
+      put_byte(s, 8);
+      if (!s.gzhead) { // s->gzhead == Z_NULL
+        put_byte(s, 0);
+        put_byte(s, 0);
+        put_byte(s, 0);
+        put_byte(s, 0);
+        put_byte(s, 0);
+        put_byte(s, s.level === 9 ? 2 :
+                    (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
+                     4 : 0));
+        put_byte(s, OS_CODE);
+        s.status = BUSY_STATE;
+      }
+      else {
+        put_byte(s, (s.gzhead.text ? 1 : 0) +
+                    (s.gzhead.hcrc ? 2 : 0) +
+                    (!s.gzhead.extra ? 0 : 4) +
+                    (!s.gzhead.name ? 0 : 8) +
+                    (!s.gzhead.comment ? 0 : 16)
+        );
+        put_byte(s, s.gzhead.time & 0xff);
+        put_byte(s, (s.gzhead.time >> 8) & 0xff);
+        put_byte(s, (s.gzhead.time >> 16) & 0xff);
+        put_byte(s, (s.gzhead.time >> 24) & 0xff);
+        put_byte(s, s.level === 9 ? 2 :
+                    (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
+                     4 : 0));
+        put_byte(s, s.gzhead.os & 0xff);
+        if (s.gzhead.extra && s.gzhead.extra.length) {
+          put_byte(s, s.gzhead.extra.length & 0xff);
+          put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
+        }
+        if (s.gzhead.hcrc) {
+          strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0);
+        }
+        s.gzindex = 0;
+        s.status = EXTRA_STATE;
+      }
+    }
+    else // DEFLATE header
+    {
+      var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
+      var level_flags = -1;
+
+      if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {
+        level_flags = 0;
+      } else if (s.level < 6) {
+        level_flags = 1;
+      } else if (s.level === 6) {
+        level_flags = 2;
+      } else {
+        level_flags = 3;
+      }
+      header |= (level_flags << 6);
+      if (s.strstart !== 0) { header |= PRESET_DICT; }
+      header += 31 - (header % 31);
+
+      s.status = BUSY_STATE;
+      putShortMSB(s, header);
+
+      /* Save the adler32 of the preset dictionary: */
+      if (s.strstart !== 0) {
+        putShortMSB(s, strm.adler >>> 16);
+        putShortMSB(s, strm.adler & 0xffff);
+      }
+      strm.adler = 1; // adler32(0L, Z_NULL, 0);
+    }
+  }
+
+//#ifdef GZIP
+  if (s.status === EXTRA_STATE) {
+    if (s.gzhead.extra/* != Z_NULL*/) {
+      beg = s.pending;  /* start of bytes to update crc */
+
+      while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {
+        if (s.pending === s.pending_buf_size) {
+          if (s.gzhead.hcrc && s.pending > beg) {
+            strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+          }
+          flush_pending(strm);
+          beg = s.pending;
+          if (s.pending === s.pending_buf_size) {
+            break;
+          }
+        }
+        put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
+        s.gzindex++;
+      }
+      if (s.gzhead.hcrc && s.pending > beg) {
+        strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+      }
+      if (s.gzindex === s.gzhead.extra.length) {
+        s.gzindex = 0;
+        s.status = NAME_STATE;
+      }
+    }
+    else {
+      s.status = NAME_STATE;
+    }
+  }
+  if (s.status === NAME_STATE) {
+    if (s.gzhead.name/* != Z_NULL*/) {
+      beg = s.pending;  /* start of bytes to update crc */
+      //int val;
+
+      do {
+        if (s.pending === s.pending_buf_size) {
+          if (s.gzhead.hcrc && s.pending > beg) {
+            strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+          }
+          flush_pending(strm);
+          beg = s.pending;
+          if (s.pending === s.pending_buf_size) {
+            val = 1;
+            break;
+          }
+        }
+        // JS specific: little magic to add zero terminator to end of string
+        if (s.gzindex < s.gzhead.name.length) {
+          val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
+        } else {
+          val = 0;
+        }
+        put_byte(s, val);
+      } while (val !== 0);
+
+      if (s.gzhead.hcrc && s.pending > beg) {
+        strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+      }
+      if (val === 0) {
+        s.gzindex = 0;
+        s.status = COMMENT_STATE;
+      }
+    }
+    else {
+      s.status = COMMENT_STATE;
+    }
+  }
+  if (s.status === COMMENT_STATE) {
+    if (s.gzhead.comment/* != Z_NULL*/) {
+      beg = s.pending;  /* start of bytes to update crc */
+      //int val;
+
+      do {
+        if (s.pending === s.pending_buf_size) {
+          if (s.gzhead.hcrc && s.pending > beg) {
+            strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+          }
+          flush_pending(strm);
+          beg = s.pending;
+          if (s.pending === s.pending_buf_size) {
+            val = 1;
+            break;
+          }
+        }
+        // JS specific: little magic to add zero terminator to end of string
+        if (s.gzindex < s.gzhead.comment.length) {
+          val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
+        } else {
+          val = 0;
+        }
+        put_byte(s, val);
+      } while (val !== 0);
+
+      if (s.gzhead.hcrc && s.pending > beg) {
+        strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
+      }
+      if (val === 0) {
+        s.status = HCRC_STATE;
+      }
+    }
+    else {
+      s.status = HCRC_STATE;
+    }
+  }
+  if (s.status === HCRC_STATE) {
+    if (s.gzhead.hcrc) {
+      if (s.pending + 2 > s.pending_buf_size) {
+        flush_pending(strm);
+      }
+      if (s.pending + 2 <= s.pending_buf_size) {
+        put_byte(s, strm.adler & 0xff);
+        put_byte(s, (strm.adler >> 8) & 0xff);
+        strm.adler = 0; //crc32(0L, Z_NULL, 0);
+        s.status = BUSY_STATE;
+      }
+    }
+    else {
+      s.status = BUSY_STATE;
+    }
+  }
+//#endif
+
+  /* Flush as much pending output as possible */
+  if (s.pending !== 0) {
+    flush_pending(strm);
+    if (strm.avail_out === 0) {
+      /* Since avail_out is 0, deflate will be called again with
+       * more output space, but possibly with both pending and
+       * avail_in equal to zero. There won't be anything to do,
+       * but this is not an error situation so make sure we
+       * return OK instead of BUF_ERROR at next call of deflate:
+       */
+      s.last_flush = -1;
+      return Z_OK;
+    }
+
+    /* Make sure there is something to do and avoid duplicate consecutive
+     * flushes. For repeated and useless calls with Z_FINISH, we keep
+     * returning Z_STREAM_END instead of Z_BUF_ERROR.
+     */
+  } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&
+    flush !== Z_FINISH) {
+    return err(strm, Z_BUF_ERROR);
+  }
+
+  /* User must not provide more input after the first FINISH: */
+  if (s.status === FINISH_STATE && strm.avail_in !== 0) {
+    return err(strm, Z_BUF_ERROR);
+  }
+
+  /* Start a new block or continue the current one.
+   */
+  if (strm.avail_in !== 0 || s.lookahead !== 0 ||
+    (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) {
+    var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) :
+      (s.strategy === Z_RLE ? deflate_rle(s, flush) :
+        configuration_table[s.level].func(s, flush));
+
+    if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {
+      s.status = FINISH_STATE;
+    }
+    if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {
+      if (strm.avail_out === 0) {
+        s.last_flush = -1;
+        /* avoid BUF_ERROR next call, see above */
+      }
+      return Z_OK;
+      /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+       * of deflate should use the same flush parameter to make sure
+       * that the flush is complete. So we don't have to output an
+       * empty block here, this will be done at next call. This also
+       * ensures that for a very small output buffer, we emit at most
+       * one empty block.
+       */
+    }
+    if (bstate === BS_BLOCK_DONE) {
+      if (flush === Z_PARTIAL_FLUSH) {
+        trees._tr_align(s);
+      }
+      else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+
+        trees._tr_stored_block(s, 0, 0, false);
+        /* For a full flush, this empty block will be recognized
+         * as a special marker by inflate_sync().
+         */
+        if (flush === Z_FULL_FLUSH) {
+          /*** CLEAR_HASH(s); ***/             /* forget history */
+          zero(s.head); // Fill with NIL (= 0);
+
+          if (s.lookahead === 0) {
+            s.strstart = 0;
+            s.block_start = 0;
+            s.insert = 0;
+          }
+        }
+      }
+      flush_pending(strm);
+      if (strm.avail_out === 0) {
+        s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+        return Z_OK;
+      }
+    }
+  }
+  //Assert(strm->avail_out > 0, "bug2");
+  //if (strm.avail_out <= 0) { throw new Error("bug2");}
+
+  if (flush !== Z_FINISH) { return Z_OK; }
+  if (s.wrap <= 0) { return Z_STREAM_END; }
+
+  /* Write the trailer */
+  if (s.wrap === 2) {
+    put_byte(s, strm.adler & 0xff);
+    put_byte(s, (strm.adler >> 8) & 0xff);
+    put_byte(s, (strm.adler >> 16) & 0xff);
+    put_byte(s, (strm.adler >> 24) & 0xff);
+    put_byte(s, strm.total_in & 0xff);
+    put_byte(s, (strm.total_in >> 8) & 0xff);
+    put_byte(s, (strm.total_in >> 16) & 0xff);
+    put_byte(s, (strm.total_in >> 24) & 0xff);
+  }
+  else
+  {
+    putShortMSB(s, strm.adler >>> 16);
+    putShortMSB(s, strm.adler & 0xffff);
+  }
+
+  flush_pending(strm);
+  /* If avail_out is zero, the application will call deflate again
+   * to flush the rest.
+   */
+  if (s.wrap > 0) { s.wrap = -s.wrap; }
+  /* write the trailer only once! */
+  return s.pending !== 0 ? Z_OK : Z_STREAM_END;
+}
+
+function deflateEnd(strm) {
+  var status;
+
+  if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
+    return Z_STREAM_ERROR;
+  }
+
+  status = strm.state.status;
+  if (status !== INIT_STATE &&
+    status !== EXTRA_STATE &&
+    status !== NAME_STATE &&
+    status !== COMMENT_STATE &&
+    status !== HCRC_STATE &&
+    status !== BUSY_STATE &&
+    status !== FINISH_STATE
+  ) {
+    return err(strm, Z_STREAM_ERROR);
+  }
+
+  strm.state = null;
+
+  return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK;
+}
+
+
+/* =========================================================================
+ * Initializes the compression dictionary from the given byte
+ * sequence without producing any compressed output.
+ */
+function deflateSetDictionary(strm, dictionary) {
+  var dictLength = dictionary.length;
+
+  var s;
+  var str, n;
+  var wrap;
+  var avail;
+  var next;
+  var input;
+  var tmpDict;
+
+  if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
+    return Z_STREAM_ERROR;
+  }
+
+  s = strm.state;
+  wrap = s.wrap;
+
+  if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {
+    return Z_STREAM_ERROR;
+  }
+
+  /* when using zlib wrappers, compute Adler-32 for provided dictionary */
+  if (wrap === 1) {
+    /* adler32(strm->adler, dictionary, dictLength); */
+    strm.adler = adler32(strm.adler, dictionary, dictLength, 0);
+  }
+
+  s.wrap = 0;   /* avoid computing Adler-32 in read_buf */
+
+  /* if dictionary would fill window, just replace the history */
+  if (dictLength >= s.w_size) {
+    if (wrap === 0) {            /* already empty otherwise */
+      /*** CLEAR_HASH(s); ***/
+      zero(s.head); // Fill with NIL (= 0);
+      s.strstart = 0;
+      s.block_start = 0;
+      s.insert = 0;
+    }
+    /* use the tail */
+    // dictionary = dictionary.slice(dictLength - s.w_size);
+    tmpDict = new utils.Buf8(s.w_size);
+    utils.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0);
+    dictionary = tmpDict;
+    dictLength = s.w_size;
+  }
+  /* insert dictionary into window and hash */
+  avail = strm.avail_in;
+  next = strm.next_in;
+  input = strm.input;
+  strm.avail_in = dictLength;
+  strm.next_in = 0;
+  strm.input = dictionary;
+  fill_window(s);
+  while (s.lookahead >= MIN_MATCH) {
+    str = s.strstart;
+    n = s.lookahead - (MIN_MATCH - 1);
+    do {
+      /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
+      s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask;
+
+      s.prev[str & s.w_mask] = s.head[s.ins_h];
+
+      s.head[s.ins_h] = str;
+      str++;
+    } while (--n);
+    s.strstart = str;
+    s.lookahead = MIN_MATCH - 1;
+    fill_window(s);
+  }
+  s.strstart += s.lookahead;
+  s.block_start = s.strstart;
+  s.insert = s.lookahead;
+  s.lookahead = 0;
+  s.match_length = s.prev_length = MIN_MATCH - 1;
+  s.match_available = 0;
+  strm.next_in = next;
+  strm.input = input;
+  strm.avail_in = avail;
+  s.wrap = wrap;
+  return Z_OK;
+}
+
+
+exports.deflateInit = deflateInit;
+exports.deflateInit2 = deflateInit2;
+exports.deflateReset = deflateReset;
+exports.deflateResetKeep = deflateResetKeep;
+exports.deflateSetHeader = deflateSetHeader;
+exports.deflate = deflate;
+exports.deflateEnd = deflateEnd;
+exports.deflateSetDictionary = deflateSetDictionary;
+exports.deflateInfo = 'pako deflate (from Nodeca project)';
+
+/* Not implemented
+exports.deflateBound = deflateBound;
+exports.deflateCopy = deflateCopy;
+exports.deflateParams = deflateParams;
+exports.deflatePending = deflatePending;
+exports.deflatePrime = deflatePrime;
+exports.deflateTune = deflateTune;
+*/
+
+},{"../utils/common":26,"./adler32":28,"./crc32":30,"./messages":36,"./trees":37}],32:[function(require,module,exports){
+'use strict';
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+function GZheader() {
+  /* true if compressed data believed to be text */
+  this.text       = 0;
+  /* modification time */
+  this.time       = 0;
+  /* extra flags (not used when writing a gzip file) */
+  this.xflags     = 0;
+  /* operating system */
+  this.os         = 0;
+  /* pointer to extra field or Z_NULL if none */
+  this.extra      = null;
+  /* extra field length (valid if extra != Z_NULL) */
+  this.extra_len  = 0; // Actually, we don't need it in JS,
+                       // but leave for few code modifications
+
+  //
+  // Setup limits is not necessary because in js we should not preallocate memory
+  // for inflate use constant limit in 65536 bytes
+  //
+
+  /* space at extra (only when reading header) */
+  // this.extra_max  = 0;
+  /* pointer to zero-terminated file name or Z_NULL */
+  this.name       = '';
+  /* space at name (only when reading header) */
+  // this.name_max   = 0;
+  /* pointer to zero-terminated comment or Z_NULL */
+  this.comment    = '';
+  /* space at comment (only when reading header) */
+  // this.comm_max   = 0;
+  /* true if there was or will be a header crc */
+  this.hcrc       = 0;
+  /* true when done reading gzip header (not used when writing a gzip file) */
+  this.done       = false;
+}
+
+module.exports = GZheader;
+
+},{}],33:[function(require,module,exports){
+'use strict';
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+// See state defs from inflate.js
+var BAD = 30;       /* got a data error -- remain here until reset */
+var TYPE = 12;      /* i: waiting for type bits, including last-flag bit */
+
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
+
+   Entry assumptions:
+
+        state.mode === LEN
+        strm.avail_in >= 6
+        strm.avail_out >= 258
+        start >= strm.avail_out
+        state.bits < 8
+
+   On return, state.mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm.avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm.avail_out >= 258 for each loop to avoid checking for
+      output space.
+ */
+module.exports = function inflate_fast(strm, start) {
+  var state;
+  var _in;                    /* local strm.input */
+  var last;                   /* have enough input while in < last */
+  var _out;                   /* local strm.output */
+  var beg;                    /* inflate()'s initial strm.output */
+  var end;                    /* while out < end, enough space available */
+//#ifdef INFLATE_STRICT
+  var dmax;                   /* maximum distance from zlib header */
+//#endif
+  var wsize;                  /* window size or zero if not using window */
+  var whave;                  /* valid bytes in the window */
+  var wnext;                  /* window write index */
+  // Use `s_window` instead `window`, avoid conflict with instrumentation tools
+  var s_window;               /* allocated sliding window, if wsize != 0 */
+  var hold;                   /* local strm.hold */
+  var bits;                   /* local strm.bits */
+  var lcode;                  /* local strm.lencode */
+  var dcode;                  /* local strm.distcode */
+  var lmask;                  /* mask for first level of length codes */
+  var dmask;                  /* mask for first level of distance codes */
+  var here;                   /* retrieved table entry */
+  var op;                     /* code bits, operation, extra bits, or */
+                              /*  window position, window bytes to copy */
+  var len;                    /* match length, unused bytes */
+  var dist;                   /* match distance */
+  var from;                   /* where to copy match from */
+  var from_source;
+
+
+  var input, output; // JS specific, because we have no pointers
+
+  /* copy state to local variables */
+  state = strm.state;
+  //here = state.here;
+  _in = strm.next_in;
+  input = strm.input;
+  last = _in + (strm.avail_in - 5);
+  _out = strm.next_out;
+  output = strm.output;
+  beg = _out - (start - strm.avail_out);
+  end = _out + (strm.avail_out - 257);
+//#ifdef INFLATE_STRICT
+  dmax = state.dmax;
+//#endif
+  wsize = state.wsize;
+  whave = state.whave;
+  wnext = state.wnext;
+  s_window = state.window;
+  hold = state.hold;
+  bits = state.bits;
+  lcode = state.lencode;
+  dcode = state.distcode;
+  lmask = (1 << state.lenbits) - 1;
+  dmask = (1 << state.distbits) - 1;
+
+
+  /* decode literals and length/distances until end-of-block or not enough
+     input data or output space */
+
+  top:
+  do {
+    if (bits < 15) {
+      hold += input[_in++] << bits;
+      bits += 8;
+      hold += input[_in++] << bits;
+      bits += 8;
+    }
+
+    here = lcode[hold & lmask];
+
+    dolen:
+    for (;;) { // Goto emulation
+      op = here >>> 24/*here.bits*/;
+      hold >>>= op;
+      bits -= op;
+      op = (here >>> 16) & 0xff/*here.op*/;
+      if (op === 0) {                          /* literal */
+        //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+        //        "inflate:         literal '%c'\n" :
+        //        "inflate:         literal 0x%02x\n", here.val));
+        output[_out++] = here & 0xffff/*here.val*/;
+      }
+      else if (op & 16) {                     /* length base */
+        len = here & 0xffff/*here.val*/;
+        op &= 15;                           /* number of extra bits */
+        if (op) {
+          if (bits < op) {
+            hold += input[_in++] << bits;
+            bits += 8;
+          }
+          len += hold & ((1 << op) - 1);
+          hold >>>= op;
+          bits -= op;
+        }
+        //Tracevv((stderr, "inflate:         length %u\n", len));
+        if (bits < 15) {
+          hold += input[_in++] << bits;
+          bits += 8;
+          hold += input[_in++] << bits;
+          bits += 8;
+        }
+        here = dcode[hold & dmask];
+
+        dodist:
+        for (;;) { // goto emulation
+          op = here >>> 24/*here.bits*/;
+          hold >>>= op;
+          bits -= op;
+          op = (here >>> 16) & 0xff/*here.op*/;
+
+          if (op & 16) {                      /* distance base */
+            dist = here & 0xffff/*here.val*/;
+            op &= 15;                       /* number of extra bits */
+            if (bits < op) {
+              hold += input[_in++] << bits;
+              bits += 8;
+              if (bits < op) {
+                hold += input[_in++] << bits;
+                bits += 8;
+              }
+            }
+            dist += hold & ((1 << op) - 1);
+//#ifdef INFLATE_STRICT
+            if (dist > dmax) {
+              strm.msg = 'invalid distance too far back';
+              state.mode = BAD;
+              break top;
+            }
+//#endif
+            hold >>>= op;
+            bits -= op;
+            //Tracevv((stderr, "inflate:         distance %u\n", dist));
+            op = _out - beg;                /* max distance in output */
+            if (dist > op) {                /* see if copy from window */
+              op = dist - op;               /* distance back in window */
+              if (op > whave) {
+                if (state.sane) {
+                  strm.msg = 'invalid distance too far back';
+                  state.mode = BAD;
+                  break top;
+                }
+
+// (!) This block is disabled in zlib defaults,
+// don't enable it for binary compatibility
+//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+//                if (len <= op - whave) {
+//                  do {
+//                    output[_out++] = 0;
+//                  } while (--len);
+//                  continue top;
+//                }
+//                len -= op - whave;
+//                do {
+//                  output[_out++] = 0;
+//                } while (--op > whave);
+//                if (op === 0) {
+//                  from = _out - dist;
+//                  do {
+//                    output[_out++] = output[from++];
+//                  } while (--len);
+//                  continue top;
+//                }
+//#endif
+              }
+              from = 0; // window index
+              from_source = s_window;
+              if (wnext === 0) {           /* very common case */
+                from += wsize - op;
+                if (op < len) {         /* some from window */
+                  len -= op;
+                  do {
+                    output[_out++] = s_window[from++];
+                  } while (--op);
+                  from = _out - dist;  /* rest from output */
+                  from_source = output;
+                }
+              }
+              else if (wnext < op) {      /* wrap around window */
+                from += wsize + wnext - op;
+                op -= wnext;
+                if (op < len) {         /* some from end of window */
+                  len -= op;
+                  do {
+                    output[_out++] = s_window[from++];
+                  } while (--op);
+                  from = 0;
+                  if (wnext < len) {  /* some from start of window */
+                    op = wnext;
+                    len -= op;
+                    do {
+                      output[_out++] = s_window[from++];
+                    } while (--op);
+                    from = _out - dist;      /* rest from output */
+                    from_source = output;
+                  }
+                }
+              }
+              else {                      /* contiguous in window */
+                from += wnext - op;
+                if (op < len) {         /* some from window */
+                  len -= op;
+                  do {
+                    output[_out++] = s_window[from++];
+                  } while (--op);
+                  from = _out - dist;  /* rest from output */
+                  from_source = output;
+                }
+              }
+              while (len > 2) {
+                output[_out++] = from_source[from++];
+                output[_out++] = from_source[from++];
+                output[_out++] = from_source[from++];
+                len -= 3;
+              }
+              if (len) {
+                output[_out++] = from_source[from++];
+                if (len > 1) {
+                  output[_out++] = from_source[from++];
+                }
+              }
+            }
+            else {
+              from = _out - dist;          /* copy direct from output */
+              do {                        /* minimum length is three */
+                output[_out++] = output[from++];
+                output[_out++] = output[from++];
+                output[_out++] = output[from++];
+                len -= 3;
+              } while (len > 2);
+              if (len) {
+                output[_out++] = output[from++];
+                if (len > 1) {
+                  output[_out++] = output[from++];
+                }
+              }
+            }
+          }
+          else if ((op & 64) === 0) {          /* 2nd level distance code */
+            here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
+            continue dodist;
+          }
+          else {
+            strm.msg = 'invalid distance code';
+            state.mode = BAD;
+            break top;
+          }
+
+          break; // need to emulate goto via "continue"
+        }
+      }
+      else if ((op & 64) === 0) {              /* 2nd level length code */
+        here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
+        continue dolen;
+      }
+      else if (op & 32) {                     /* end-of-block */
+        //Tracevv((stderr, "inflate:         end of block\n"));
+        state.mode = TYPE;
+        break top;
+      }
+      else {
+        strm.msg = 'invalid literal/length code';
+        state.mode = BAD;
+        break top;
+      }
+
+      break; // need to emulate goto via "continue"
+    }
+  } while (_in < last && _out < end);
+
+  /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+  len = bits >> 3;
+  _in -= len;
+  bits -= len << 3;
+  hold &= (1 << bits) - 1;
+
+  /* update state and return */
+  strm.next_in = _in;
+  strm.next_out = _out;
+  strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
+  strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
+  state.hold = hold;
+  state.bits = bits;
+  return;
+};
+
+},{}],34:[function(require,module,exports){
+'use strict';
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+var utils         = require('../utils/common');
+var adler32       = require('./adler32');
+var crc32         = require('./crc32');
+var inflate_fast  = require('./inffast');
+var inflate_table = require('./inftrees');
+
+var CODES = 0;
+var LENS = 1;
+var DISTS = 2;
+
+/* Public constants ==========================================================*/
+/* ===========================================================================*/
+
+
+/* Allowed flush values; see deflate() and inflate() below for details */
+//var Z_NO_FLUSH      = 0;
+//var Z_PARTIAL_FLUSH = 1;
+//var Z_SYNC_FLUSH    = 2;
+//var Z_FULL_FLUSH    = 3;
+var Z_FINISH        = 4;
+var Z_BLOCK         = 5;
+var Z_TREES         = 6;
+
+
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+var Z_OK            = 0;
+var Z_STREAM_END    = 1;
+var Z_NEED_DICT     = 2;
+//var Z_ERRNO         = -1;
+var Z_STREAM_ERROR  = -2;
+var Z_DATA_ERROR    = -3;
+var Z_MEM_ERROR     = -4;
+var Z_BUF_ERROR     = -5;
+//var Z_VERSION_ERROR = -6;
+
+/* The deflate compression method */
+var Z_DEFLATED  = 8;
+
+
+/* STATES ====================================================================*/
+/* ===========================================================================*/
+
+
+var    HEAD = 1;       /* i: waiting for magic header */
+var    FLAGS = 2;      /* i: waiting for method and flags (gzip) */
+var    TIME = 3;       /* i: waiting for modification time (gzip) */
+var    OS = 4;         /* i: waiting for extra flags and operating system (gzip) */
+var    EXLEN = 5;      /* i: waiting for extra length (gzip) */
+var    EXTRA = 6;      /* i: waiting for extra bytes (gzip) */
+var    NAME = 7;       /* i: waiting for end of file name (gzip) */
+var    COMMENT = 8;    /* i: waiting for end of comment (gzip) */
+var    HCRC = 9;       /* i: waiting for header crc (gzip) */
+var    DICTID = 10;    /* i: waiting for dictionary check value */
+var    DICT = 11;      /* waiting for inflateSetDictionary() call */
+var        TYPE = 12;      /* i: waiting for type bits, including last-flag bit */
+var        TYPEDO = 13;    /* i: same, but skip check to exit inflate on new block */
+var        STORED = 14;    /* i: waiting for stored size (length and complement) */
+var        COPY_ = 15;     /* i/o: same as COPY below, but only first time in */
+var        COPY = 16;      /* i/o: waiting for input or output to copy stored block */
+var        TABLE = 17;     /* i: waiting for dynamic block table lengths */
+var        LENLENS = 18;   /* i: waiting for code length code lengths */
+var        CODELENS = 19;  /* i: waiting for length/lit and distance code lengths */
+var            LEN_ = 20;      /* i: same as LEN below, but only first time in */
+var            LEN = 21;       /* i: waiting for length/lit/eob code */
+var            LENEXT = 22;    /* i: waiting for length extra bits */
+var            DIST = 23;      /* i: waiting for distance code */
+var            DISTEXT = 24;   /* i: waiting for distance extra bits */
+var            MATCH = 25;     /* o: waiting for output space to copy string */
+var            LIT = 26;       /* o: waiting for output space to write literal */
+var    CHECK = 27;     /* i: waiting for 32-bit check value */
+var    LENGTH = 28;    /* i: waiting for 32-bit length (gzip) */
+var    DONE = 29;      /* finished check, done -- remain here until reset */
+var    BAD = 30;       /* got a data error -- remain here until reset */
+var    MEM = 31;       /* got an inflate() memory error -- remain here until reset */
+var    SYNC = 32;      /* looking for synchronization bytes to restart inflate() */
+
+/* ===========================================================================*/
+
+
+
+var ENOUGH_LENS = 852;
+var ENOUGH_DISTS = 592;
+//var ENOUGH =  (ENOUGH_LENS+ENOUGH_DISTS);
+
+var MAX_WBITS = 15;
+/* 32K LZ77 window */
+var DEF_WBITS = MAX_WBITS;
+
+
+function zswap32(q) {
+  return  (((q >>> 24) & 0xff) +
+          ((q >>> 8) & 0xff00) +
+          ((q & 0xff00) << 8) +
+          ((q & 0xff) << 24));
+}
+
+
+function InflateState() {
+  this.mode = 0;             /* current inflate mode */
+  this.last = false;          /* true if processing last block */
+  this.wrap = 0;              /* bit 0 true for zlib, bit 1 true for gzip */
+  this.havedict = false;      /* true if dictionary provided */
+  this.flags = 0;             /* gzip header method and flags (0 if zlib) */
+  this.dmax = 0;              /* zlib header max distance (INFLATE_STRICT) */
+  this.check = 0;             /* protected copy of check value */
+  this.total = 0;             /* protected copy of output count */
+  // TODO: may be {}
+  this.head = null;           /* where to save gzip header information */
+
+  /* sliding window */
+  this.wbits = 0;             /* log base 2 of requested window size */
+  this.wsize = 0;             /* window size or zero if not using window */
+  this.whave = 0;             /* valid bytes in the window */
+  this.wnext = 0;             /* window write index */
+  this.window = null;         /* allocated sliding window, if needed */
+
+  /* bit accumulator */
+  this.hold = 0;              /* input bit accumulator */
+  this.bits = 0;              /* number of bits in "in" */
+
+  /* for string and stored block copying */
+  this.length = 0;            /* literal or length of data to copy */
+  this.offset = 0;            /* distance back to copy string from */
+
+  /* for table and code decoding */
+  this.extra = 0;             /* extra bits needed */
+
+  /* fixed and dynamic code tables */
+  this.lencode = null;          /* starting table for length/literal codes */
+  this.distcode = null;         /* starting table for distance codes */
+  this.lenbits = 0;           /* index bits for lencode */
+  this.distbits = 0;          /* index bits for distcode */
+
+  /* dynamic table building */
+  this.ncode = 0;             /* number of code length code lengths */
+  this.nlen = 0;              /* number of length code lengths */
+  this.ndist = 0;             /* number of distance code lengths */
+  this.have = 0;              /* number of code lengths in lens[] */
+  this.next = null;              /* next available space in codes[] */
+
+  this.lens = new utils.Buf16(320); /* temporary storage for code lengths */
+  this.work = new utils.Buf16(288); /* work area for code table building */
+
+  /*
+   because we don't have pointers in js, we use lencode and distcode directly
+   as buffers so we don't need codes
+  */
+  //this.codes = new utils.Buf32(ENOUGH);       /* space for code tables */
+  this.lendyn = null;              /* dynamic table for length/literal codes (JS specific) */
+  this.distdyn = null;             /* dynamic table for distance codes (JS specific) */
+  this.sane = 0;                   /* if false, allow invalid distance too far */
+  this.back = 0;                   /* bits back of last unprocessed length/lit */
+  this.was = 0;                    /* initial length of match */
+}
+
+function inflateResetKeep(strm) {
+  var state;
+
+  if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+  state = strm.state;
+  strm.total_in = strm.total_out = state.total = 0;
+  strm.msg = ''; /*Z_NULL*/
+  if (state.wrap) {       /* to support ill-conceived Java test suite */
+    strm.adler = state.wrap & 1;
+  }
+  state.mode = HEAD;
+  state.last = 0;
+  state.havedict = 0;
+  state.dmax = 32768;
+  state.head = null/*Z_NULL*/;
+  state.hold = 0;
+  state.bits = 0;
+  //state.lencode = state.distcode = state.next = state.codes;
+  state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS);
+  state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS);
+
+  state.sane = 1;
+  state.back = -1;
+  //Tracev((stderr, "inflate: reset\n"));
+  return Z_OK;
+}
+
+function inflateReset(strm) {
+  var state;
+
+  if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+  state = strm.state;
+  state.wsize = 0;
+  state.whave = 0;
+  state.wnext = 0;
+  return inflateResetKeep(strm);
+
+}
+
+function inflateReset2(strm, windowBits) {
+  var wrap;
+  var state;
+
+  /* get the state */
+  if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+  state = strm.state;
+
+  /* extract wrap request from windowBits parameter */
+  if (windowBits < 0) {
+    wrap = 0;
+    windowBits = -windowBits;
+  }
+  else {
+    wrap = (windowBits >> 4) + 1;
+    if (windowBits < 48) {
+      windowBits &= 15;
+    }
+  }
+
+  /* set number of window bits, free window if different */
+  if (windowBits && (windowBits < 8 || windowBits > 15)) {
+    return Z_STREAM_ERROR;
+  }
+  if (state.window !== null && state.wbits !== windowBits) {
+    state.window = null;
+  }
+
+  /* update state and reset the rest of it */
+  state.wrap = wrap;
+  state.wbits = windowBits;
+  return inflateReset(strm);
+}
+
+function inflateInit2(strm, windowBits) {
+  var ret;
+  var state;
+
+  if (!strm) { return Z_STREAM_ERROR; }
+  //strm.msg = Z_NULL;                 /* in case we return an error */
+
+  state = new InflateState();
+
+  //if (state === Z_NULL) return Z_MEM_ERROR;
+  //Tracev((stderr, "inflate: allocated\n"));
+  strm.state = state;
+  state.window = null/*Z_NULL*/;
+  ret = inflateReset2(strm, windowBits);
+  if (ret !== Z_OK) {
+    strm.state = null/*Z_NULL*/;
+  }
+  return ret;
+}
+
+function inflateInit(strm) {
+  return inflateInit2(strm, DEF_WBITS);
+}
+
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding.  Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter.  This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time.  However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+var virgin = true;
+
+var lenfix, distfix; // We have no pointers in JS, so keep tables separate
+
+function fixedtables(state) {
+  /* build fixed huffman tables if first call (may not be thread safe) */
+  if (virgin) {
+    var sym;
+
+    lenfix = new utils.Buf32(512);
+    distfix = new utils.Buf32(32);
+
+    /* literal/length table */
+    sym = 0;
+    while (sym < 144) { state.lens[sym++] = 8; }
+    while (sym < 256) { state.lens[sym++] = 9; }
+    while (sym < 280) { state.lens[sym++] = 7; }
+    while (sym < 288) { state.lens[sym++] = 8; }
+
+    inflate_table(LENS,  state.lens, 0, 288, lenfix,   0, state.work, { bits: 9 });
+
+    /* distance table */
+    sym = 0;
+    while (sym < 32) { state.lens[sym++] = 5; }
+
+    inflate_table(DISTS, state.lens, 0, 32,   distfix, 0, state.work, { bits: 5 });
+
+    /* do this just once */
+    virgin = false;
+  }
+
+  state.lencode = lenfix;
+  state.lenbits = 9;
+  state.distcode = distfix;
+  state.distbits = 5;
+}
+
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning.  If window does not exist yet, create it.  This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+function updatewindow(strm, src, end, copy) {
+  var dist;
+  var state = strm.state;
+
+  /* if it hasn't been done already, allocate space for the window */
+  if (state.window === null) {
+    state.wsize = 1 << state.wbits;
+    state.wnext = 0;
+    state.whave = 0;
+
+    state.window = new utils.Buf8(state.wsize);
+  }
+
+  /* copy state->wsize or less output bytes into the circular window */
+  if (copy >= state.wsize) {
+    utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0);
+    state.wnext = 0;
+    state.whave = state.wsize;
+  }
+  else {
+    dist = state.wsize - state.wnext;
+    if (dist > copy) {
+      dist = copy;
+    }
+    //zmemcpy(state->window + state->wnext, end - copy, dist);
+    utils.arraySet(state.window, src, end - copy, dist, state.wnext);
+    copy -= dist;
+    if (copy) {
+      //zmemcpy(state->window, end - copy, copy);
+      utils.arraySet(state.window, src, end - copy, copy, 0);
+      state.wnext = copy;
+      state.whave = state.wsize;
+    }
+    else {
+      state.wnext += dist;
+      if (state.wnext === state.wsize) { state.wnext = 0; }
+      if (state.whave < state.wsize) { state.whave += dist; }
+    }
+  }
+  return 0;
+}
+
+function inflate(strm, flush) {
+  var state;
+  var input, output;          // input/output buffers
+  var next;                   /* next input INDEX */
+  var put;                    /* next output INDEX */
+  var have, left;             /* available input and output */
+  var hold;                   /* bit buffer */
+  var bits;                   /* bits in bit buffer */
+  var _in, _out;              /* save starting available input and output */
+  var copy;                   /* number of stored or match bytes to copy */
+  var from;                   /* where to copy match bytes from */
+  var from_source;
+  var here = 0;               /* current decoding table entry */
+  var here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
+  //var last;                   /* parent table entry */
+  var last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
+  var len;                    /* length to copy for repeats, bits to drop */
+  var ret;                    /* return code */
+  var hbuf = new utils.Buf8(4);    /* buffer for gzip header crc calculation */
+  var opts;
+
+  var n; // temporary var for NEED_BITS
+
+  var order = /* permutation of code lengths */
+    [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
+
+
+  if (!strm || !strm.state || !strm.output ||
+      (!strm.input && strm.avail_in !== 0)) {
+    return Z_STREAM_ERROR;
+  }
+
+  state = strm.state;
+  if (state.mode === TYPE) { state.mode = TYPEDO; }    /* skip check */
+
+
+  //--- LOAD() ---
+  put = strm.next_out;
+  output = strm.output;
+  left = strm.avail_out;
+  next = strm.next_in;
+  input = strm.input;
+  have = strm.avail_in;
+  hold = state.hold;
+  bits = state.bits;
+  //---
+
+  _in = have;
+  _out = left;
+  ret = Z_OK;
+
+  inf_leave: // goto emulation
+  for (;;) {
+    switch (state.mode) {
+      case HEAD:
+        if (state.wrap === 0) {
+          state.mode = TYPEDO;
+          break;
+        }
+        //=== NEEDBITS(16);
+        while (bits < 16) {
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+        }
+        //===//
+        if ((state.wrap & 2) && hold === 0x8b1f) {  /* gzip header */
+          state.check = 0/*crc32(0L, Z_NULL, 0)*/;
+          //=== CRC2(state.check, hold);
+          hbuf[0] = hold & 0xff;
+          hbuf[1] = (hold >>> 8) & 0xff;
+          state.check = crc32(state.check, hbuf, 2, 0);
+          //===//
+
+          //=== INITBITS();
+          hold = 0;
+          bits = 0;
+          //===//
+          state.mode = FLAGS;
+          break;
+        }
+        state.flags = 0;           /* expect zlib header */
+        if (state.head) {
+          state.head.done = false;
+        }
+        if (!(state.wrap & 1) ||   /* check if zlib header allowed */
+          (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
+          strm.msg = 'incorrect header check';
+          state.mode = BAD;
+          break;
+        }
+        if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {
+          strm.msg = 'unknown compression method';
+          state.mode = BAD;
+          break;
+        }
+        //--- DROPBITS(4) ---//
+        hold >>>= 4;
+        bits -= 4;
+        //---//
+        len = (hold & 0x0f)/*BITS(4)*/ + 8;
+        if (state.wbits === 0) {
+          state.wbits = len;
+        }
+        else if (len > state.wbits) {
+          strm.msg = 'invalid window size';
+          state.mode = BAD;
+          break;
+        }
+        state.dmax = 1 << len;
+        //Tracev((stderr, "inflate:   zlib header ok\n"));
+        strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
+        state.mode = hold & 0x200 ? DICTID : TYPE;
+        //=== INITBITS();
+        hold = 0;
+        bits = 0;
+        //===//
+        break;
+      case FLAGS:
+        //=== NEEDBITS(16); */
+        while (bits < 16) {
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+        }
+        //===//
+        state.flags = hold;
+        if ((state.flags & 0xff) !== Z_DEFLATED) {
+          strm.msg = 'unknown compression method';
+          state.mode = BAD;
+          break;
+        }
+        if (state.flags & 0xe000) {
+          strm.msg = 'unknown header flags set';
+          state.mode = BAD;
+          break;
+        }
+        if (state.head) {
+          state.head.text = ((hold >> 8) & 1);
+        }
+        if (state.flags & 0x0200) {
+          //=== CRC2(state.check, hold);
+          hbuf[0] = hold & 0xff;
+          hbuf[1] = (hold >>> 8) & 0xff;
+          state.check = crc32(state.check, hbuf, 2, 0);
+          //===//
+        }
+        //=== INITBITS();
+        hold = 0;
+        bits = 0;
+        //===//
+        state.mode = TIME;
+        /* falls through */
+      case TIME:
+        //=== NEEDBITS(32); */
+        while (bits < 32) {
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+        }
+        //===//
+        if (state.head) {
+          state.head.time = hold;
+        }
+        if (state.flags & 0x0200) {
+          //=== CRC4(state.check, hold)
+          hbuf[0] = hold & 0xff;
+          hbuf[1] = (hold >>> 8) & 0xff;
+          hbuf[2] = (hold >>> 16) & 0xff;
+          hbuf[3] = (hold >>> 24) & 0xff;
+          state.check = crc32(state.check, hbuf, 4, 0);
+          //===
+        }
+        //=== INITBITS();
+        hold = 0;
+        bits = 0;
+        //===//
+        state.mode = OS;
+        /* falls through */
+      case OS:
+        //=== NEEDBITS(16); */
+        while (bits < 16) {
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+        }
+        //===//
+        if (state.head) {
+          state.head.xflags = (hold & 0xff);
+          state.head.os = (hold >> 8);
+        }
+        if (state.flags & 0x0200) {
+          //=== CRC2(state.check, hold);
+          hbuf[0] = hold & 0xff;
+          hbuf[1] = (hold >>> 8) & 0xff;
+          state.check = crc32(state.check, hbuf, 2, 0);
+          //===//
+        }
+        //=== INITBITS();
+        hold = 0;
+        bits = 0;
+        //===//
+        state.mode = EXLEN;
+        /* falls through */
+      case EXLEN:
+        if (state.flags & 0x0400) {
+          //=== NEEDBITS(16); */
+          while (bits < 16) {
+            if (have === 0) { break inf_leave; }
+            have--;
+            hold += input[next++] << bits;
+            bits += 8;
+          }
+          //===//
+          state.length = hold;
+          if (state.head) {
+            state.head.extra_len = hold;
+          }
+          if (state.flags & 0x0200) {
+            //=== CRC2(state.check, hold);
+            hbuf[0] = hold & 0xff;
+            hbuf[1] = (hold >>> 8) & 0xff;
+            state.check = crc32(state.check, hbuf, 2, 0);
+            //===//
+          }
+          //=== INITBITS();
+          hold = 0;
+          bits = 0;
+          //===//
+        }
+        else if (state.head) {
+          state.head.extra = null/*Z_NULL*/;
+        }
+        state.mode = EXTRA;
+        /* falls through */
+      case EXTRA:
+        if (state.flags & 0x0400) {
+          copy = state.length;
+          if (copy > have) { copy = have; }
+          if (copy) {
+            if (state.head) {
+              len = state.head.extra_len - state.length;
+              if (!state.head.extra) {
+                // Use untyped array for more convenient processing later
+                state.head.extra = new Array(state.head.extra_len);
+              }
+              utils.arraySet(
+                state.head.extra,
+                input,
+                next,
+                // extra field is limited to 65536 bytes
+                // - no need for additional size check
+                copy,
+                /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
+                len
+              );
+              //zmemcpy(state.head.extra + len, next,
+              //        len + copy > state.head.extra_max ?
+              //        state.head.extra_max - len : copy);
+            }
+            if (state.flags & 0x0200) {
+              state.check = crc32(state.check, input, copy, next);
+            }
+            have -= copy;
+            next += copy;
+            state.length -= copy;
+          }
+          if (state.length) { break inf_leave; }
+        }
+        state.length = 0;
+        state.mode = NAME;
+        /* falls through */
+      case NAME:
+        if (state.flags & 0x0800) {
+          if (have === 0) { break inf_leave; }
+          copy = 0;
+          do {
+            // TODO: 2 or 1 bytes?
+            len = input[next + copy++];
+            /* use constant limit because in js we should not preallocate memory */
+            if (state.head && len &&
+                (state.length < 65536 /*state.head.name_max*/)) {
+              state.head.name += String.fromCharCode(len);
+            }
+          } while (len && copy < have);
+
+          if (state.flags & 0x0200) {
+            state.check = crc32(state.check, input, copy, next);
+          }
+          have -= copy;
+          next += copy;
+          if (len) { break inf_leave; }
+        }
+        else if (state.head) {
+          state.head.name = null;
+        }
+        state.length = 0;
+        state.mode = COMMENT;
+        /* falls through */
+      case COMMENT:
+        if (state.flags & 0x1000) {
+          if (have === 0) { break inf_leave; }
+          copy = 0;
+          do {
+            len = input[next + copy++];
+            /* use constant limit because in js we should not preallocate memory */
+            if (state.head && len &&
+                (state.length < 65536 /*state.head.comm_max*/)) {
+              state.head.comment += String.fromCharCode(len);
+            }
+          } while (len && copy < have);
+          if (state.flags & 0x0200) {
+            state.check = crc32(state.check, input, copy, next);
+          }
+          have -= copy;
+          next += copy;
+          if (len) { break inf_leave; }
+        }
+        else if (state.head) {
+          state.head.comment = null;
+        }
+        state.mode = HCRC;
+        /* falls through */
+      case HCRC:
+        if (state.flags & 0x0200) {
+          //=== NEEDBITS(16); */
+          while (bits < 16) {
+            if (have === 0) { break inf_leave; }
+            have--;
+            hold += input[next++] << bits;
+            bits += 8;
+          }
+          //===//
+          if (hold !== (state.check & 0xffff)) {
+            strm.msg = 'header crc mismatch';
+            state.mode = BAD;
+            break;
+          }
+          //=== INITBITS();
+          hold = 0;
+          bits = 0;
+          //===//
+        }
+        if (state.head) {
+          state.head.hcrc = ((state.flags >> 9) & 1);
+          state.head.done = true;
+        }
+        strm.adler = state.check = 0;
+        state.mode = TYPE;
+        break;
+      case DICTID:
+        //=== NEEDBITS(32); */
+        while (bits < 32) {
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+        }
+        //===//
+        strm.adler = state.check = zswap32(hold);
+        //=== INITBITS();
+        hold = 0;
+        bits = 0;
+        //===//
+        state.mode = DICT;
+        /* falls through */
+      case DICT:
+        if (state.havedict === 0) {
+          //--- RESTORE() ---
+          strm.next_out = put;
+          strm.avail_out = left;
+          strm.next_in = next;
+          strm.avail_in = have;
+          state.hold = hold;
+          state.bits = bits;
+          //---
+          return Z_NEED_DICT;
+        }
+        strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
+        state.mode = TYPE;
+        /* falls through */
+      case TYPE:
+        if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }
+        /* falls through */
+      case TYPEDO:
+        if (state.last) {
+          //--- BYTEBITS() ---//
+          hold >>>= bits & 7;
+          bits -= bits & 7;
+          //---//
+          state.mode = CHECK;
+          break;
+        }
+        //=== NEEDBITS(3); */
+        while (bits < 3) {
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+        }
+        //===//
+        state.last = (hold & 0x01)/*BITS(1)*/;
+        //--- DROPBITS(1) ---//
+        hold >>>= 1;
+        bits -= 1;
+        //---//
+
+        switch ((hold & 0x03)/*BITS(2)*/) {
+          case 0:                             /* stored block */
+            //Tracev((stderr, "inflate:     stored block%s\n",
+            //        state.last ? " (last)" : ""));
+            state.mode = STORED;
+            break;
+          case 1:                             /* fixed block */
+            fixedtables(state);
+            //Tracev((stderr, "inflate:     fixed codes block%s\n",
+            //        state.last ? " (last)" : ""));
+            state.mode = LEN_;             /* decode codes */
+            if (flush === Z_TREES) {
+              //--- DROPBITS(2) ---//
+              hold >>>= 2;
+              bits -= 2;
+              //---//
+              break inf_leave;
+            }
+            break;
+          case 2:                             /* dynamic block */
+            //Tracev((stderr, "inflate:     dynamic codes block%s\n",
+            //        state.last ? " (last)" : ""));
+            state.mode = TABLE;
+            break;
+          case 3:
+            strm.msg = 'invalid block type';
+            state.mode = BAD;
+        }
+        //--- DROPBITS(2) ---//
+        hold >>>= 2;
+        bits -= 2;
+        //---//
+        break;
+      case STORED:
+        //--- BYTEBITS() ---// /* go to byte boundary */
+        hold >>>= bits & 7;
+        bits -= bits & 7;
+        //---//
+        //=== NEEDBITS(32); */
+        while (bits < 32) {
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+        }
+        //===//
+        if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
+          strm.msg = 'invalid stored block lengths';
+          state.mode = BAD;
+          break;
+        }
+        state.length = hold & 0xffff;
+        //Tracev((stderr, "inflate:       stored length %u\n",
+        //        state.length));
+        //=== INITBITS();
+        hold = 0;
+        bits = 0;
+        //===//
+        state.mode = COPY_;
+        if (flush === Z_TREES) { break inf_leave; }
+        /* falls through */
+      case COPY_:
+        state.mode = COPY;
+        /* falls through */
+      case COPY:
+        copy = state.length;
+        if (copy) {
+          if (copy > have) { copy = have; }
+          if (copy > left) { copy = left; }
+          if (copy === 0) { break inf_leave; }
+          //--- zmemcpy(put, next, copy); ---
+          utils.arraySet(output, input, next, copy, put);
+          //---//
+          have -= copy;
+          next += copy;
+          left -= copy;
+          put += copy;
+          state.length -= copy;
+          break;
+        }
+        //Tracev((stderr, "inflate:       stored end\n"));
+        state.mode = TYPE;
+        break;
+      case TABLE:
+        //=== NEEDBITS(14); */
+        while (bits < 14) {
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+        }
+        //===//
+        state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
+        //--- DROPBITS(5) ---//
+        hold >>>= 5;
+        bits -= 5;
+        //---//
+        state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
+        //--- DROPBITS(5) ---//
+        hold >>>= 5;
+        bits -= 5;
+        //---//
+        state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
+        //--- DROPBITS(4) ---//
+        hold >>>= 4;
+        bits -= 4;
+        //---//
+//#ifndef PKZIP_BUG_WORKAROUND
+        if (state.nlen > 286 || state.ndist > 30) {
+          strm.msg = 'too many length or distance symbols';
+          state.mode = BAD;
+          break;
+        }
+//#endif
+        //Tracev((stderr, "inflate:       table sizes ok\n"));
+        state.have = 0;
+        state.mode = LENLENS;
+        /* falls through */
+      case LENLENS:
+        while (state.have < state.ncode) {
+          //=== NEEDBITS(3);
+          while (bits < 3) {
+            if (have === 0) { break inf_leave; }
+            have--;
+            hold += input[next++] << bits;
+            bits += 8;
+          }
+          //===//
+          state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
+          //--- DROPBITS(3) ---//
+          hold >>>= 3;
+          bits -= 3;
+          //---//
+        }
+        while (state.have < 19) {
+          state.lens[order[state.have++]] = 0;
+        }
+        // We have separate tables & no pointers. 2 commented lines below not needed.
+        //state.next = state.codes;
+        //state.lencode = state.next;
+        // Switch to use dynamic table
+        state.lencode = state.lendyn;
+        state.lenbits = 7;
+
+        opts = { bits: state.lenbits };
+        ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);
+        state.lenbits = opts.bits;
+
+        if (ret) {
+          strm.msg = 'invalid code lengths set';
+          state.mode = BAD;
+          break;
+        }
+        //Tracev((stderr, "inflate:       code lengths ok\n"));
+        state.have = 0;
+        state.mode = CODELENS;
+        /* falls through */
+      case CODELENS:
+        while (state.have < state.nlen + state.ndist) {
+          for (;;) {
+            here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
+            here_bits = here >>> 24;
+            here_op = (here >>> 16) & 0xff;
+            here_val = here & 0xffff;
+
+            if ((here_bits) <= bits) { break; }
+            //--- PULLBYTE() ---//
+            if (have === 0) { break inf_leave; }
+            have--;
+            hold += input[next++] << bits;
+            bits += 8;
+            //---//
+          }
+          if (here_val < 16) {
+            //--- DROPBITS(here.bits) ---//
+            hold >>>= here_bits;
+            bits -= here_bits;
+            //---//
+            state.lens[state.have++] = here_val;
+          }
+          else {
+            if (here_val === 16) {
+              //=== NEEDBITS(here.bits + 2);
+              n = here_bits + 2;
+              while (bits < n) {
+                if (have === 0) { break inf_leave; }
+                have--;
+                hold += input[next++] << bits;
+                bits += 8;
+              }
+              //===//
+              //--- DROPBITS(here.bits) ---//
+              hold >>>= here_bits;
+              bits -= here_bits;
+              //---//
+              if (state.have === 0) {
+                strm.msg = 'invalid bit length repeat';
+                state.mode = BAD;
+                break;
+              }
+              len = state.lens[state.have - 1];
+              copy = 3 + (hold & 0x03);//BITS(2);
+              //--- DROPBITS(2) ---//
+              hold >>>= 2;
+              bits -= 2;
+              //---//
+            }
+            else if (here_val === 17) {
+              //=== NEEDBITS(here.bits + 3);
+              n = here_bits + 3;
+              while (bits < n) {
+                if (have === 0) { break inf_leave; }
+                have--;
+                hold += input[next++] << bits;
+                bits += 8;
+              }
+              //===//
+              //--- DROPBITS(here.bits) ---//
+              hold >>>= here_bits;
+              bits -= here_bits;
+              //---//
+              len = 0;
+              copy = 3 + (hold & 0x07);//BITS(3);
+              //--- DROPBITS(3) ---//
+              hold >>>= 3;
+              bits -= 3;
+              //---//
+            }
+            else {
+              //=== NEEDBITS(here.bits + 7);
+              n = here_bits + 7;
+              while (bits < n) {
+                if (have === 0) { break inf_leave; }
+                have--;
+                hold += input[next++] << bits;
+                bits += 8;
+              }
+              //===//
+              //--- DROPBITS(here.bits) ---//
+              hold >>>= here_bits;
+              bits -= here_bits;
+              //---//
+              len = 0;
+              copy = 11 + (hold & 0x7f);//BITS(7);
+              //--- DROPBITS(7) ---//
+              hold >>>= 7;
+              bits -= 7;
+              //---//
+            }
+            if (state.have + copy > state.nlen + state.ndist) {
+              strm.msg = 'invalid bit length repeat';
+              state.mode = BAD;
+              break;
+            }
+            while (copy--) {
+              state.lens[state.have++] = len;
+            }
+          }
+        }
+
+        /* handle error breaks in while */
+        if (state.mode === BAD) { break; }
+
+        /* check for end-of-block code (better have one) */
+        if (state.lens[256] === 0) {
+          strm.msg = 'invalid code -- missing end-of-block';
+          state.mode = BAD;
+          break;
+        }
+
+        /* build code tables -- note: do not change the lenbits or distbits
+           values here (9 and 6) without reading the comments in inftrees.h
+           concerning the ENOUGH constants, which depend on those values */
+        state.lenbits = 9;
+
+        opts = { bits: state.lenbits };
+        ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
+        // We have separate tables & no pointers. 2 commented lines below not needed.
+        // state.next_index = opts.table_index;
+        state.lenbits = opts.bits;
+        // state.lencode = state.next;
+
+        if (ret) {
+          strm.msg = 'invalid literal/lengths set';
+          state.mode = BAD;
+          break;
+        }
+
+        state.distbits = 6;
+        //state.distcode.copy(state.codes);
+        // Switch to use dynamic table
+        state.distcode = state.distdyn;
+        opts = { bits: state.distbits };
+        ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
+        // We have separate tables & no pointers. 2 commented lines below not needed.
+        // state.next_index = opts.table_index;
+        state.distbits = opts.bits;
+        // state.distcode = state.next;
+
+        if (ret) {
+          strm.msg = 'invalid distances set';
+          state.mode = BAD;
+          break;
+        }
+        //Tracev((stderr, 'inflate:       codes ok\n'));
+        state.mode = LEN_;
+        if (flush === Z_TREES) { break inf_leave; }
+        /* falls through */
+      case LEN_:
+        state.mode = LEN;
+        /* falls through */
+      case LEN:
+        if (have >= 6 && left >= 258) {
+          //--- RESTORE() ---
+          strm.next_out = put;
+          strm.avail_out = left;
+          strm.next_in = next;
+          strm.avail_in = have;
+          state.hold = hold;
+          state.bits = bits;
+          //---
+          inflate_fast(strm, _out);
+          //--- LOAD() ---
+          put = strm.next_out;
+          output = strm.output;
+          left = strm.avail_out;
+          next = strm.next_in;
+          input = strm.input;
+          have = strm.avail_in;
+          hold = state.hold;
+          bits = state.bits;
+          //---
+
+          if (state.mode === TYPE) {
+            state.back = -1;
+          }
+          break;
+        }
+        state.back = 0;
+        for (;;) {
+          here = state.lencode[hold & ((1 << state.lenbits) - 1)];  /*BITS(state.lenbits)*/
+          here_bits = here >>> 24;
+          here_op = (here >>> 16) & 0xff;
+          here_val = here & 0xffff;
+
+          if (here_bits <= bits) { break; }
+          //--- PULLBYTE() ---//
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+          //---//
+        }
+        if (here_op && (here_op & 0xf0) === 0) {
+          last_bits = here_bits;
+          last_op = here_op;
+          last_val = here_val;
+          for (;;) {
+            here = state.lencode[last_val +
+                    ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
+            here_bits = here >>> 24;
+            here_op = (here >>> 16) & 0xff;
+            here_val = here & 0xffff;
+
+            if ((last_bits + here_bits) <= bits) { break; }
+            //--- PULLBYTE() ---//
+            if (have === 0) { break inf_leave; }
+            have--;
+            hold += input[next++] << bits;
+            bits += 8;
+            //---//
+          }
+          //--- DROPBITS(last.bits) ---//
+          hold >>>= last_bits;
+          bits -= last_bits;
+          //---//
+          state.back += last_bits;
+        }
+        //--- DROPBITS(here.bits) ---//
+        hold >>>= here_bits;
+        bits -= here_bits;
+        //---//
+        state.back += here_bits;
+        state.length = here_val;
+        if (here_op === 0) {
+          //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+          //        "inflate:         literal '%c'\n" :
+          //        "inflate:         literal 0x%02x\n", here.val));
+          state.mode = LIT;
+          break;
+        }
+        if (here_op & 32) {
+          //Tracevv((stderr, "inflate:         end of block\n"));
+          state.back = -1;
+          state.mode = TYPE;
+          break;
+        }
+        if (here_op & 64) {
+          strm.msg = 'invalid literal/length code';
+          state.mode = BAD;
+          break;
+        }
+        state.extra = here_op & 15;
+        state.mode = LENEXT;
+        /* falls through */
+      case LENEXT:
+        if (state.extra) {
+          //=== NEEDBITS(state.extra);
+          n = state.extra;
+          while (bits < n) {
+            if (have === 0) { break inf_leave; }
+            have--;
+            hold += input[next++] << bits;
+            bits += 8;
+          }
+          //===//
+          state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
+          //--- DROPBITS(state.extra) ---//
+          hold >>>= state.extra;
+          bits -= state.extra;
+          //---//
+          state.back += state.extra;
+        }
+        //Tracevv((stderr, "inflate:         length %u\n", state.length));
+        state.was = state.length;
+        state.mode = DIST;
+        /* falls through */
+      case DIST:
+        for (;;) {
+          here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/
+          here_bits = here >>> 24;
+          here_op = (here >>> 16) & 0xff;
+          here_val = here & 0xffff;
+
+          if ((here_bits) <= bits) { break; }
+          //--- PULLBYTE() ---//
+          if (have === 0) { break inf_leave; }
+          have--;
+          hold += input[next++] << bits;
+          bits += 8;
+          //---//
+        }
+        if ((here_op & 0xf0) === 0) {
+          last_bits = here_bits;
+          last_op = here_op;
+          last_val = here_val;
+          for (;;) {
+            here = state.distcode[last_val +
+                    ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
+            here_bits = here >>> 24;
+            here_op = (here >>> 16) & 0xff;
+            here_val = here & 0xffff;
+
+            if ((last_bits + here_bits) <= bits) { break; }
+            //--- PULLBYTE() ---//
+            if (have === 0) { break inf_leave; }
+            have--;
+            hold += input[next++] << bits;
+            bits += 8;
+            //---//
+          }
+          //--- DROPBITS(last.bits) ---//
+          hold >>>= last_bits;
+          bits -= last_bits;
+          //---//
+          state.back += last_bits;
+        }
+        //--- DROPBITS(here.bits) ---//
+        hold >>>= here_bits;
+        bits -= here_bits;
+        //---//
+        state.back += here_bits;
+        if (here_op & 64) {
+          strm.msg = 'invalid distance code';
+          state.mode = BAD;
+          break;
+        }
+        state.offset = here_val;
+        state.extra = (here_op) & 15;
+        state.mode = DISTEXT;
+        /* falls through */
+      case DISTEXT:
+        if (state.extra) {
+          //=== NEEDBITS(state.extra);
+          n = state.extra;
+          while (bits < n) {
+            if (have === 0) { break inf_leave; }
+            have--;
+            hold += input[next++] << bits;
+            bits += 8;
+          }
+          //===//
+          state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
+          //--- DROPBITS(state.extra) ---//
+          hold >>>= state.extra;
+          bits -= state.extra;
+          //---//
+          state.back += state.extra;
+        }
+//#ifdef INFLATE_STRICT
+        if (state.offset > state.dmax) {
+          strm.msg = 'invalid distance too far back';
+          state.mode = BAD;
+          break;
+        }
+//#endif
+        //Tracevv((stderr, "inflate:         distance %u\n", state.offset));
+        state.mode = MATCH;
+        /* falls through */
+      case MATCH:
+        if (left === 0) { break inf_leave; }
+        copy = _out - left;
+        if (state.offset > copy) {         /* copy from window */
+          copy = state.offset - copy;
+          if (copy > state.whave) {
+            if (state.sane) {
+              strm.msg = 'invalid distance too far back';
+              state.mode = BAD;
+              break;
+            }
+// (!) This block is disabled in zlib defaults,
+// don't enable it for binary compatibility
+//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+//          Trace((stderr, "inflate.c too far\n"));
+//          copy -= state.whave;
+//          if (copy > state.length) { copy = state.length; }
+//          if (copy > left) { copy = left; }
+//          left -= copy;
+//          state.length -= copy;
+//          do {
+//            output[put++] = 0;
+//          } while (--copy);
+//          if (state.length === 0) { state.mode = LEN; }
+//          break;
+//#endif
+          }
+          if (copy > state.wnext) {
+            copy -= state.wnext;
+            from = state.wsize - copy;
+          }
+          else {
+            from = state.wnext - copy;
+          }
+          if (copy > state.length) { copy = state.length; }
+          from_source = state.window;
+        }
+        else {                              /* copy from output */
+          from_source = output;
+          from = put - state.offset;
+          copy = state.length;
+        }
+        if (copy > left) { copy = left; }
+        left -= copy;
+        state.length -= copy;
+        do {
+          output[put++] = from_source[from++];
+        } while (--copy);
+        if (state.length === 0) { state.mode = LEN; }
+        break;
+      case LIT:
+        if (left === 0) { break inf_leave; }
+        output[put++] = state.length;
+        left--;
+        state.mode = LEN;
+        break;
+      case CHECK:
+        if (state.wrap) {
+          //=== NEEDBITS(32);
+          while (bits < 32) {
+            if (have === 0) { break inf_leave; }
+            have--;
+            // Use '|' instead of '+' to make sure that result is signed
+            hold |= input[next++] << bits;
+            bits += 8;
+          }
+          //===//
+          _out -= left;
+          strm.total_out += _out;
+          state.total += _out;
+          if (_out) {
+            strm.adler = state.check =
+                /*UPDATE(state.check, put - _out, _out);*/
+                (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out));
+
+          }
+          _out = left;
+          // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too
+          if ((state.flags ? hold : zswap32(hold)) !== state.check) {
+            strm.msg = 'incorrect data check';
+            state.mode = BAD;
+            break;
+          }
+          //=== INITBITS();
+          hold = 0;
+          bits = 0;
+          //===//
+          //Tracev((stderr, "inflate:   check matches trailer\n"));
+        }
+        state.mode = LENGTH;
+        /* falls through */
+      case LENGTH:
+        if (state.wrap && state.flags) {
+          //=== NEEDBITS(32);
+          while (bits < 32) {
+            if (have === 0) { break inf_leave; }
+            have--;
+            hold += input[next++] << bits;
+            bits += 8;
+          }
+          //===//
+          if (hold !== (state.total & 0xffffffff)) {
+            strm.msg = 'incorrect length check';
+            state.mode = BAD;
+            break;
+          }
+          //=== INITBITS();
+          hold = 0;
+          bits = 0;
+          //===//
+          //Tracev((stderr, "inflate:   length matches trailer\n"));
+        }
+        state.mode = DONE;
+        /* falls through */
+      case DONE:
+        ret = Z_STREAM_END;
+        break inf_leave;
+      case BAD:
+        ret = Z_DATA_ERROR;
+        break inf_leave;
+      case MEM:
+        return Z_MEM_ERROR;
+      case SYNC:
+        /* falls through */
+      default:
+        return Z_STREAM_ERROR;
+    }
+  }
+
+  // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"
+
+  /*
+     Return from inflate(), updating the total counts and the check value.
+     If there was no progress during the inflate() call, return a buffer
+     error.  Call updatewindow() to create and/or update the window state.
+     Note: a memory error from inflate() is non-recoverable.
+   */
+
+  //--- RESTORE() ---
+  strm.next_out = put;
+  strm.avail_out = left;
+  strm.next_in = next;
+  strm.avail_in = have;
+  state.hold = hold;
+  state.bits = bits;
+  //---
+
+  if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&
+                      (state.mode < CHECK || flush !== Z_FINISH))) {
+    if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) {
+      state.mode = MEM;
+      return Z_MEM_ERROR;
+    }
+  }
+  _in -= strm.avail_in;
+  _out -= strm.avail_out;
+  strm.total_in += _in;
+  strm.total_out += _out;
+  state.total += _out;
+  if (state.wrap && _out) {
+    strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/
+      (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out));
+  }
+  strm.data_type = state.bits + (state.last ? 64 : 0) +
+                    (state.mode === TYPE ? 128 : 0) +
+                    (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
+  if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) {
+    ret = Z_BUF_ERROR;
+  }
+  return ret;
+}
+
+function inflateEnd(strm) {
+
+  if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {
+    return Z_STREAM_ERROR;
+  }
+
+  var state = strm.state;
+  if (state.window) {
+    state.window = null;
+  }
+  strm.state = null;
+  return Z_OK;
+}
+
+function inflateGetHeader(strm, head) {
+  var state;
+
+  /* check state */
+  if (!strm || !strm.state) { return Z_STREAM_ERROR; }
+  state = strm.state;
+  if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; }
+
+  /* save header structure */
+  state.head = head;
+  head.done = false;
+  return Z_OK;
+}
+
+function inflateSetDictionary(strm, dictionary) {
+  var dictLength = dictionary.length;
+
+  var state;
+  var dictid;
+  var ret;
+
+  /* check state */
+  if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; }
+  state = strm.state;
+
+  if (state.wrap !== 0 && state.mode !== DICT) {
+    return Z_STREAM_ERROR;
+  }
+
+  /* check for correct dictionary identifier */
+  if (state.mode === DICT) {
+    dictid = 1; /* adler32(0, null, 0)*/
+    /* dictid = adler32(dictid, dictionary, dictLength); */
+    dictid = adler32(dictid, dictionary, dictLength, 0);
+    if (dictid !== state.check) {
+      return Z_DATA_ERROR;
+    }
+  }
+  /* copy dictionary to window using updatewindow(), which will amend the
+   existing dictionary if appropriate */
+  ret = updatewindow(strm, dictionary, dictLength, dictLength);
+  if (ret) {
+    state.mode = MEM;
+    return Z_MEM_ERROR;
+  }
+  state.havedict = 1;
+  // Tracev((stderr, "inflate:   dictionary set\n"));
+  return Z_OK;
+}
+
+exports.inflateReset = inflateReset;
+exports.inflateReset2 = inflateReset2;
+exports.inflateResetKeep = inflateResetKeep;
+exports.inflateInit = inflateInit;
+exports.inflateInit2 = inflateInit2;
+exports.inflate = inflate;
+exports.inflateEnd = inflateEnd;
+exports.inflateGetHeader = inflateGetHeader;
+exports.inflateSetDictionary = inflateSetDictionary;
+exports.inflateInfo = 'pako inflate (from Nodeca project)';
+
+/* Not implemented
+exports.inflateCopy = inflateCopy;
+exports.inflateGetDictionary = inflateGetDictionary;
+exports.inflateMark = inflateMark;
+exports.inflatePrime = inflatePrime;
+exports.inflateSync = inflateSync;
+exports.inflateSyncPoint = inflateSyncPoint;
+exports.inflateUndermine = inflateUndermine;
+*/
+
+},{"../utils/common":26,"./adler32":28,"./crc32":30,"./inffast":33,"./inftrees":35}],35:[function(require,module,exports){
+'use strict';
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+var utils = require('../utils/common');
+
+var MAXBITS = 15;
+var ENOUGH_LENS = 852;
+var ENOUGH_DISTS = 592;
+//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
+
+var CODES = 0;
+var LENS = 1;
+var DISTS = 2;
+
+var lbase = [ /* Length codes 257..285 base */
+  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+  35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+];
+
+var lext = [ /* Length codes 257..285 extra */
+  16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+  19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
+];
+
+var dbase = [ /* Distance codes 0..29 base */
+  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+  257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+  8193, 12289, 16385, 24577, 0, 0
+];
+
+var dext = [ /* Distance codes 0..29 extra */
+  16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+  23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+  28, 28, 29, 29, 64, 64
+];
+
+module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts)
+{
+  var bits = opts.bits;
+      //here = opts.here; /* table entry for duplication */
+
+  var len = 0;               /* a code's length in bits */
+  var sym = 0;               /* index of code symbols */
+  var min = 0, max = 0;          /* minimum and maximum code lengths */
+  var root = 0;              /* number of index bits for root table */
+  var curr = 0;              /* number of index bits for current table */
+  var drop = 0;              /* code bits to drop for sub-table */
+  var left = 0;                   /* number of prefix codes available */
+  var used = 0;              /* code entries in table used */
+  var huff = 0;              /* Huffman code */
+  var incr;              /* for incrementing code, index */
+  var fill;              /* index for replicating entries */
+  var low;               /* low bits for current root entry */
+  var mask;              /* mask for low root bits */
+  var next;             /* next available space in table */
+  var base = null;     /* base value table to use */
+  var base_index = 0;
+//  var shoextra;    /* extra bits table to use */
+  var end;                    /* use base and extra for symbol > end */
+  var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1];    /* number of codes of each length */
+  var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1];     /* offsets in table for each length */
+  var extra = null;
+  var extra_index = 0;
+
+  var here_bits, here_op, here_val;
+
+  /*
+   Process a set of code lengths to create a canonical Huffman code.  The
+   code lengths are lens[0..codes-1].  Each length corresponds to the
+   symbols 0..codes-1.  The Huffman code is generated by first sorting the
+   symbols by length from short to long, and retaining the symbol order
+   for codes with equal lengths.  Then the code starts with all zero bits
+   for the first code of the shortest length, and the codes are integer
+   increments for the same length, and zeros are appended as the length
+   increases.  For the deflate format, these bits are stored backwards
+   from their more natural integer increment ordering, and so when the
+   decoding tables are built in the large loop below, the integer codes
+   are incremented backwards.
+
+   This routine assumes, but does not check, that all of the entries in
+   lens[] are in the range 0..MAXBITS.  The caller must assure this.
+   1..MAXBITS is interpreted as that code length.  zero means that that
+   symbol does not occur in this code.
+
+   The codes are sorted by computing a count of codes for each length,
+   creating from that a table of starting indices for each length in the
+   sorted table, and then entering the symbols in order in the sorted
+   table.  The sorted table is work[], with that space being provided by
+   the caller.
+
+   The length counts are used for other purposes as well, i.e. finding
+   the minimum and maximum length codes, determining if there are any
+   codes at all, checking for a valid set of lengths, and looking ahead
+   at length counts to determine sub-table sizes when building the
+   decoding tables.
+   */
+
+  /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+  for (len = 0; len <= MAXBITS; len++) {
+    count[len] = 0;
+  }
+  for (sym = 0; sym < codes; sym++) {
+    count[lens[lens_index + sym]]++;
+  }
+
+  /* bound code lengths, force root to be within code lengths */
+  root = bits;
+  for (max = MAXBITS; max >= 1; max--) {
+    if (count[max] !== 0) { break; }
+  }
+  if (root > max) {
+    root = max;
+  }
+  if (max === 0) {                     /* no symbols to code at all */
+    //table.op[opts.table_index] = 64;  //here.op = (var char)64;    /* invalid code marker */
+    //table.bits[opts.table_index] = 1;   //here.bits = (var char)1;
+    //table.val[opts.table_index++] = 0;   //here.val = (var short)0;
+    table[table_index++] = (1 << 24) | (64 << 16) | 0;
+
+
+    //table.op[opts.table_index] = 64;
+    //table.bits[opts.table_index] = 1;
+    //table.val[opts.table_index++] = 0;
+    table[table_index++] = (1 << 24) | (64 << 16) | 0;
+
+    opts.bits = 1;
+    return 0;     /* no symbols, but wait for decoding to report error */
+  }
+  for (min = 1; min < max; min++) {
+    if (count[min] !== 0) { break; }
+  }
+  if (root < min) {
+    root = min;
+  }
+
+  /* check for an over-subscribed or incomplete set of lengths */
+  left = 1;
+  for (len = 1; len <= MAXBITS; len++) {
+    left <<= 1;
+    left -= count[len];
+    if (left < 0) {
+      return -1;
+    }        /* over-subscribed */
+  }
+  if (left > 0 && (type === CODES || max !== 1)) {
+    return -1;                      /* incomplete set */
+  }
+
+  /* generate offsets into symbol table for each length for sorting */
+  offs[1] = 0;
+  for (len = 1; len < MAXBITS; len++) {
+    offs[len + 1] = offs[len] + count[len];
+  }
+
+  /* sort symbols by length, by symbol order within each length */
+  for (sym = 0; sym < codes; sym++) {
+    if (lens[lens_index + sym] !== 0) {
+      work[offs[lens[lens_index + sym]]++] = sym;
+    }
+  }
+
+  /*
+   Create and fill in decoding tables.  In this loop, the table being
+   filled is at next and has curr index bits.  The code being used is huff
+   with length len.  That code is converted to an index by dropping drop
+   bits off of the bottom.  For codes where len is less than drop + curr,
+   those top drop + curr - len bits are incremented through all values to
+   fill the table with replicated entries.
+
+   root is the number of index bits for the root table.  When len exceeds
+   root, sub-tables are created pointed to by the root entry with an index
+   of the low root bits of huff.  This is saved in low to check for when a
+   new sub-table should be started.  drop is zero when the root table is
+   being filled, and drop is root when sub-tables are being filled.
+
+   When a new sub-table is needed, it is necessary to look ahead in the
+   code lengths to determine what size sub-table is needed.  The length
+   counts are used for this, and so count[] is decremented as codes are
+   entered in the tables.
+
+   used keeps track of how many table entries have been allocated from the
+   provided *table space.  It is checked for LENS and DIST tables against
+   the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+   the initial root table size constants.  See the comments in inftrees.h
+   for more information.
+
+   sym increments through all symbols, and the loop terminates when
+   all codes of length max, i.e. all codes, have been processed.  This
+   routine permits incomplete codes, so another loop after this one fills
+   in the rest of the decoding tables with invalid code markers.
+   */
+
+  /* set up for code type */
+  // poor man optimization - use if-else instead of switch,
+  // to avoid deopts in old v8
+  if (type === CODES) {
+    base = extra = work;    /* dummy value--not used */
+    end = 19;
+
+  } else if (type === LENS) {
+    base = lbase;
+    base_index -= 257;
+    extra = lext;
+    extra_index -= 257;
+    end = 256;
+
+  } else {                    /* DISTS */
+    base = dbase;
+    extra = dext;
+    end = -1;
+  }
+
+  /* initialize opts for loop */
+  huff = 0;                   /* starting code */
+  sym = 0;                    /* starting code symbol */
+  len = min;                  /* starting code length */
+  next = table_index;              /* current table to fill in */
+  curr = root;                /* current table index bits */
+  drop = 0;                   /* current bits to drop from code for index */
+  low = -1;                   /* trigger new sub-table when len > root */
+  used = 1 << root;          /* use root table entries */
+  mask = used - 1;            /* mask for comparing low */
+
+  /* check available table space */
+  if ((type === LENS && used > ENOUGH_LENS) ||
+    (type === DISTS && used > ENOUGH_DISTS)) {
+    return 1;
+  }
+
+  /* process all codes and make table entries */
+  for (;;) {
+    /* create table entry */
+    here_bits = len - drop;
+    if (work[sym] < end) {
+      here_op = 0;
+      here_val = work[sym];
+    }
+    else if (work[sym] > end) {
+      here_op = extra[extra_index + work[sym]];
+      here_val = base[base_index + work[sym]];
+    }
+    else {
+      here_op = 32 + 64;         /* end of block */
+      here_val = 0;
+    }
+
+    /* replicate for those indices with low len bits equal to huff */
+    incr = 1 << (len - drop);
+    fill = 1 << curr;
+    min = fill;                 /* save offset to next table */
+    do {
+      fill -= incr;
+      table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
+    } while (fill !== 0);
+
+    /* backwards increment the len-bit code huff */
+    incr = 1 << (len - 1);
+    while (huff & incr) {
+      incr >>= 1;
+    }
+    if (incr !== 0) {
+      huff &= incr - 1;
+      huff += incr;
+    } else {
+      huff = 0;
+    }
+
+    /* go to next symbol, update count, len */
+    sym++;
+    if (--count[len] === 0) {
+      if (len === max) { break; }
+      len = lens[lens_index + work[sym]];
+    }
+
+    /* create new sub-table if needed */
+    if (len > root && (huff & mask) !== low) {
+      /* if first time, transition to sub-tables */
+      if (drop === 0) {
+        drop = root;
+      }
+
+      /* increment past last table */
+      next += min;            /* here min is 1 << curr */
+
+      /* determine length of next table */
+      curr = len - drop;
+      left = 1 << curr;
+      while (curr + drop < max) {
+        left -= count[curr + drop];
+        if (left <= 0) { break; }
+        curr++;
+        left <<= 1;
+      }
+
+      /* check for enough space */
+      used += 1 << curr;
+      if ((type === LENS && used > ENOUGH_LENS) ||
+        (type === DISTS && used > ENOUGH_DISTS)) {
+        return 1;
+      }
+
+      /* point entry in root table to sub-table */
+      low = huff & mask;
+      /*table.op[low] = curr;
+      table.bits[low] = root;
+      table.val[low] = next - opts.table_index;*/
+      table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
+    }
+  }
+
+  /* fill in remaining table entry if code is incomplete (guaranteed to have
+   at most one remaining entry, since if the code is incomplete, the
+   maximum code length that was allowed to get this far is one bit) */
+  if (huff !== 0) {
+    //table.op[next + huff] = 64;            /* invalid code marker */
+    //table.bits[next + huff] = len - drop;
+    //table.val[next + huff] = 0;
+    table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
+  }
+
+  /* set return parameters */
+  //opts.table_index += used;
+  opts.bits = root;
+  return 0;
+};
+
+},{"../utils/common":26}],36:[function(require,module,exports){
+'use strict';
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+module.exports = {
+  2:      'need dictionary',     /* Z_NEED_DICT       2  */
+  1:      'stream end',          /* Z_STREAM_END      1  */
+  0:      '',                    /* Z_OK              0  */
+  '-1':   'file error',          /* Z_ERRNO         (-1) */
+  '-2':   'stream error',        /* Z_STREAM_ERROR  (-2) */
+  '-3':   'data error',          /* Z_DATA_ERROR    (-3) */
+  '-4':   'insufficient memory', /* Z_MEM_ERROR     (-4) */
+  '-5':   'buffer error',        /* Z_BUF_ERROR     (-5) */
+  '-6':   'incompatible version' /* Z_VERSION_ERROR (-6) */
+};
+
+},{}],37:[function(require,module,exports){
+'use strict';
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+/* eslint-disable space-unary-ops */
+
+var utils = require('../utils/common');
+
+/* Public constants ==========================================================*/
+/* ===========================================================================*/
+
+
+//var Z_FILTERED          = 1;
+//var Z_HUFFMAN_ONLY      = 2;
+//var Z_RLE               = 3;
+var Z_FIXED               = 4;
+//var Z_DEFAULT_STRATEGY  = 0;
+
+/* Possible values of the data_type field (though see inflate()) */
+var Z_BINARY              = 0;
+var Z_TEXT                = 1;
+//var Z_ASCII             = 1; // = Z_TEXT
+var Z_UNKNOWN             = 2;
+
+/*============================================================================*/
+
+
+function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }
+
+// From zutil.h
+
+var STORED_BLOCK = 0;
+var STATIC_TREES = 1;
+var DYN_TREES    = 2;
+/* The three kinds of block type */
+
+var MIN_MATCH    = 3;
+var MAX_MATCH    = 258;
+/* The minimum and maximum match lengths */
+
+// From deflate.h
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+var LENGTH_CODES  = 29;
+/* number of length codes, not counting the special END_BLOCK code */
+
+var LITERALS      = 256;
+/* number of literal bytes 0..255 */
+
+var L_CODES       = LITERALS + 1 + LENGTH_CODES;
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+var D_CODES       = 30;
+/* number of distance codes */
+
+var BL_CODES      = 19;
+/* number of codes used to transfer the bit lengths */
+
+var HEAP_SIZE     = 2 * L_CODES + 1;
+/* maximum heap size */
+
+var MAX_BITS      = 15;
+/* All codes must not exceed MAX_BITS bits */
+
+var Buf_size      = 16;
+/* size of bit buffer in bi_buf */
+
+
+/* ===========================================================================
+ * Constants
+ */
+
+var MAX_BL_BITS = 7;
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+var END_BLOCK   = 256;
+/* end of block literal code */
+
+var REP_3_6     = 16;
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+var REPZ_3_10   = 17;
+/* repeat a zero length 3-10 times  (3 bits of repeat count) */
+
+var REPZ_11_138 = 18;
+/* repeat a zero length 11-138 times  (7 bits of repeat count) */
+
+/* eslint-disable comma-spacing,array-bracket-spacing */
+var extra_lbits =   /* extra bits for each length code */
+  [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0];
+
+var extra_dbits =   /* extra bits for each distance code */
+  [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];
+
+var extra_blbits =  /* extra bits for each bit length code */
+  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7];
+
+var bl_order =
+  [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];
+/* eslint-enable comma-spacing,array-bracket-spacing */
+
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+// We pre-fill arrays with 0 to avoid uninitialized gaps
+
+var DIST_CODE_LEN = 512; /* see definition of array dist_code below */
+
+// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1
+var static_ltree  = new Array((L_CODES + 2) * 2);
+zero(static_ltree);
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+var static_dtree  = new Array(D_CODES * 2);
+zero(static_dtree);
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+var _dist_code    = new Array(DIST_CODE_LEN);
+zero(_dist_code);
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+var _length_code  = new Array(MAX_MATCH - MIN_MATCH + 1);
+zero(_length_code);
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+var base_length   = new Array(LENGTH_CODES);
+zero(base_length);
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+var base_dist     = new Array(D_CODES);
+zero(base_dist);
+/* First normalized distance for each code (0 = distance of 1) */
+
+
+function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {
+
+  this.static_tree  = static_tree;  /* static tree or NULL */
+  this.extra_bits   = extra_bits;   /* extra bits for each code or NULL */
+  this.extra_base   = extra_base;   /* base index for extra_bits */
+  this.elems        = elems;        /* max number of elements in the tree */
+  this.max_length   = max_length;   /* max bit length for the codes */
+
+  // show if `static_tree` has data or dummy - needed for monomorphic objects
+  this.has_stree    = static_tree && static_tree.length;
+}
+
+
+var static_l_desc;
+var static_d_desc;
+var static_bl_desc;
+
+
+function TreeDesc(dyn_tree, stat_desc) {
+  this.dyn_tree = dyn_tree;     /* the dynamic tree */
+  this.max_code = 0;            /* largest code with non zero frequency */
+  this.stat_desc = stat_desc;   /* the corresponding static tree */
+}
+
+
+
+function d_code(dist) {
+  return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
+}
+
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+function put_short(s, w) {
+//    put_byte(s, (uch)((w) & 0xff));
+//    put_byte(s, (uch)((ush)(w) >> 8));
+  s.pending_buf[s.pending++] = (w) & 0xff;
+  s.pending_buf[s.pending++] = (w >>> 8) & 0xff;
+}
+
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+function send_bits(s, value, length) {
+  if (s.bi_valid > (Buf_size - length)) {
+    s.bi_buf |= (value << s.bi_valid) & 0xffff;
+    put_short(s, s.bi_buf);
+    s.bi_buf = value >> (Buf_size - s.bi_valid);
+    s.bi_valid += length - Buf_size;
+  } else {
+    s.bi_buf |= (value << s.bi_valid) & 0xffff;
+    s.bi_valid += length;
+  }
+}
+
+
+function send_code(s, c, tree) {
+  send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/);
+}
+
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+function bi_reverse(code, len) {
+  var res = 0;
+  do {
+    res |= code & 1;
+    code >>>= 1;
+    res <<= 1;
+  } while (--len > 0);
+  return res >>> 1;
+}
+
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+function bi_flush(s) {
+  if (s.bi_valid === 16) {
+    put_short(s, s.bi_buf);
+    s.bi_buf = 0;
+    s.bi_valid = 0;
+
+  } else if (s.bi_valid >= 8) {
+    s.pending_buf[s.pending++] = s.bi_buf & 0xff;
+    s.bi_buf >>= 8;
+    s.bi_valid -= 8;
+  }
+}
+
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ *    above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ *     array bl_count contains the frequencies for each bit length.
+ *     The length opt_len is updated; static_len is also updated if stree is
+ *     not null.
+ */
+function gen_bitlen(s, desc)
+//    deflate_state *s;
+//    tree_desc *desc;    /* the tree descriptor */
+{
+  var tree            = desc.dyn_tree;
+  var max_code        = desc.max_code;
+  var stree           = desc.stat_desc.static_tree;
+  var has_stree       = desc.stat_desc.has_stree;
+  var extra           = desc.stat_desc.extra_bits;
+  var base            = desc.stat_desc.extra_base;
+  var max_length      = desc.stat_desc.max_length;
+  var h;              /* heap index */
+  var n, m;           /* iterate over the tree elements */
+  var bits;           /* bit length */
+  var xbits;          /* extra bits */
+  var f;              /* frequency */
+  var overflow = 0;   /* number of elements with bit length too large */
+
+  for (bits = 0; bits <= MAX_BITS; bits++) {
+    s.bl_count[bits] = 0;
+  }
+
+  /* In a first pass, compute the optimal bit lengths (which may
+   * overflow in the case of the bit length tree).
+   */
+  tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */
+
+  for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
+    n = s.heap[h];
+    bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;
+    if (bits > max_length) {
+      bits = max_length;
+      overflow++;
+    }
+    tree[n * 2 + 1]/*.Len*/ = bits;
+    /* We overwrite tree[n].Dad which is no longer needed */
+
+    if (n > max_code) { continue; } /* not a leaf node */
+
+    s.bl_count[bits]++;
+    xbits = 0;
+    if (n >= base) {
+      xbits = extra[n - base];
+    }
+    f = tree[n * 2]/*.Freq*/;
+    s.opt_len += f * (bits + xbits);
+    if (has_stree) {
+      s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);
+    }
+  }
+  if (overflow === 0) { return; }
+
+  // Trace((stderr,"\nbit length overflow\n"));
+  /* This happens for example on obj2 and pic of the Calgary corpus */
+
+  /* Find the first bit length which could increase: */
+  do {
+    bits = max_length - 1;
+    while (s.bl_count[bits] === 0) { bits--; }
+    s.bl_count[bits]--;      /* move one leaf down the tree */
+    s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */
+    s.bl_count[max_length]--;
+    /* The brother of the overflow item also moves one step up,
+     * but this does not affect bl_count[max_length]
+     */
+    overflow -= 2;
+  } while (overflow > 0);
+
+  /* Now recompute all bit lengths, scanning in increasing frequency.
+   * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+   * lengths instead of fixing only the wrong ones. This idea is taken
+   * from 'ar' written by Haruhiko Okumura.)
+   */
+  for (bits = max_length; bits !== 0; bits--) {
+    n = s.bl_count[bits];
+    while (n !== 0) {
+      m = s.heap[--h];
+      if (m > max_code) { continue; }
+      if (tree[m * 2 + 1]/*.Len*/ !== bits) {
+        // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+        s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;
+        tree[m * 2 + 1]/*.Len*/ = bits;
+      }
+      n--;
+    }
+  }
+}
+
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ *     zero code length.
+ */
+function gen_codes(tree, max_code, bl_count)
+//    ct_data *tree;             /* the tree to decorate */
+//    int max_code;              /* largest code with non zero frequency */
+//    ushf *bl_count;            /* number of codes at each bit length */
+{
+  var next_code = new Array(MAX_BITS + 1); /* next code value for each bit length */
+  var code = 0;              /* running code value */
+  var bits;                  /* bit index */
+  var n;                     /* code index */
+
+  /* The distribution counts are first used to generate the code values
+   * without bit reversal.
+   */
+  for (bits = 1; bits <= MAX_BITS; bits++) {
+    next_code[bits] = code = (code + bl_count[bits - 1]) << 1;
+  }
+  /* Check that the bit counts in bl_count are consistent. The last code
+   * must be all ones.
+   */
+  //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+  //        "inconsistent bit counts");
+  //Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+  for (n = 0;  n <= max_code; n++) {
+    var len = tree[n * 2 + 1]/*.Len*/;
+    if (len === 0) { continue; }
+    /* Now reverse the bits */
+    tree[n * 2]/*.Code*/ = bi_reverse(next_code[len]++, len);
+
+    //Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+    //     n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+  }
+}
+
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+function tr_static_init() {
+  var n;        /* iterates over tree elements */
+  var bits;     /* bit counter */
+  var length;   /* length value */
+  var code;     /* code value */
+  var dist;     /* distance index */
+  var bl_count = new Array(MAX_BITS + 1);
+  /* number of codes at each bit length for an optimal tree */
+
+  // do check in _tr_init()
+  //if (static_init_done) return;
+
+  /* For some embedded targets, global variables are not initialized: */
+/*#ifdef NO_INIT_GLOBAL_POINTERS
+  static_l_desc.static_tree = static_ltree;
+  static_l_desc.extra_bits = extra_lbits;
+  static_d_desc.static_tree = static_dtree;
+  static_d_desc.extra_bits = extra_dbits;
+  static_bl_desc.extra_bits = extra_blbits;
+#endif*/
+
+  /* Initialize the mapping length (0..255) -> length code (0..28) */
+  length = 0;
+  for (code = 0; code < LENGTH_CODES - 1; code++) {
+    base_length[code] = length;
+    for (n = 0; n < (1 << extra_lbits[code]); n++) {
+      _length_code[length++] = code;
+    }
+  }
+  //Assert (length == 256, "tr_static_init: length != 256");
+  /* Note that the length 255 (match length 258) can be represented
+   * in two different ways: code 284 + 5 bits or code 285, so we
+   * overwrite length_code[255] to use the best encoding:
+   */
+  _length_code[length - 1] = code;
+
+  /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+  dist = 0;
+  for (code = 0; code < 16; code++) {
+    base_dist[code] = dist;
+    for (n = 0; n < (1 << extra_dbits[code]); n++) {
+      _dist_code[dist++] = code;
+    }
+  }
+  //Assert (dist == 256, "tr_static_init: dist != 256");
+  dist >>= 7; /* from now on, all distances are divided by 128 */
+  for (; code < D_CODES; code++) {
+    base_dist[code] = dist << 7;
+    for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
+      _dist_code[256 + dist++] = code;
+    }
+  }
+  //Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+  /* Construct the codes of the static literal tree */
+  for (bits = 0; bits <= MAX_BITS; bits++) {
+    bl_count[bits] = 0;
+  }
+
+  n = 0;
+  while (n <= 143) {
+    static_ltree[n * 2 + 1]/*.Len*/ = 8;
+    n++;
+    bl_count[8]++;
+  }
+  while (n <= 255) {
+    static_ltree[n * 2 + 1]/*.Len*/ = 9;
+    n++;
+    bl_count[9]++;
+  }
+  while (n <= 279) {
+    static_ltree[n * 2 + 1]/*.Len*/ = 7;
+    n++;
+    bl_count[7]++;
+  }
+  while (n <= 287) {
+    static_ltree[n * 2 + 1]/*.Len*/ = 8;
+    n++;
+    bl_count[8]++;
+  }
+  /* Codes 286 and 287 do not exist, but we must include them in the
+   * tree construction to get a canonical Huffman tree (longest code
+   * all ones)
+   */
+  gen_codes(static_ltree, L_CODES + 1, bl_count);
+
+  /* The static distance tree is trivial: */
+  for (n = 0; n < D_CODES; n++) {
+    static_dtree[n * 2 + 1]/*.Len*/ = 5;
+    static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5);
+  }
+
+  // Now data ready and we can init static trees
+  static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+  static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS);
+  static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0,         BL_CODES, MAX_BL_BITS);
+
+  //static_init_done = true;
+}
+
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+function init_block(s) {
+  var n; /* iterates over tree elements */
+
+  /* Initialize the trees. */
+  for (n = 0; n < L_CODES;  n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; }
+  for (n = 0; n < D_CODES;  n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; }
+  for (n = 0; n < BL_CODES; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; }
+
+  s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1;
+  s.opt_len = s.static_len = 0;
+  s.last_lit = s.matches = 0;
+}
+
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+function bi_windup(s)
+{
+  if (s.bi_valid > 8) {
+    put_short(s, s.bi_buf);
+  } else if (s.bi_valid > 0) {
+    //put_byte(s, (Byte)s->bi_buf);
+    s.pending_buf[s.pending++] = s.bi_buf;
+  }
+  s.bi_buf = 0;
+  s.bi_valid = 0;
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+function copy_block(s, buf, len, header)
+//DeflateState *s;
+//charf    *buf;    /* the input data */
+//unsigned len;     /* its length */
+//int      header;  /* true if block header must be written */
+{
+  bi_windup(s);        /* align on byte boundary */
+
+  if (header) {
+    put_short(s, len);
+    put_short(s, ~len);
+  }
+//  while (len--) {
+//    put_byte(s, *buf++);
+//  }
+  utils.arraySet(s.pending_buf, s.window, buf, len, s.pending);
+  s.pending += len;
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+function smaller(tree, n, m, depth) {
+  var _n2 = n * 2;
+  var _m2 = m * 2;
+  return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||
+         (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));
+}
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+function pqdownheap(s, tree, k)
+//    deflate_state *s;
+//    ct_data *tree;  /* the tree to restore */
+//    int k;               /* node to move down */
+{
+  var v = s.heap[k];
+  var j = k << 1;  /* left son of k */
+  while (j <= s.heap_len) {
+    /* Set j to the smallest of the two sons: */
+    if (j < s.heap_len &&
+      smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {
+      j++;
+    }
+    /* Exit if v is smaller than both sons */
+    if (smaller(tree, v, s.heap[j], s.depth)) { break; }
+
+    /* Exchange v with the smallest son */
+    s.heap[k] = s.heap[j];
+    k = j;
+
+    /* And continue down the tree, setting j to the left son of k */
+    j <<= 1;
+  }
+  s.heap[k] = v;
+}
+
+
+// inlined manually
+// var SMALLEST = 1;
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+function compress_block(s, ltree, dtree)
+//    deflate_state *s;
+//    const ct_data *ltree; /* literal tree */
+//    const ct_data *dtree; /* distance tree */
+{
+  var dist;           /* distance of matched string */
+  var lc;             /* match length or unmatched char (if dist == 0) */
+  var lx = 0;         /* running index in l_buf */
+  var code;           /* the code to send */
+  var extra;          /* number of extra bits to send */
+
+  if (s.last_lit !== 0) {
+    do {
+      dist = (s.pending_buf[s.d_buf + lx * 2] << 8) | (s.pending_buf[s.d_buf + lx * 2 + 1]);
+      lc = s.pending_buf[s.l_buf + lx];
+      lx++;
+
+      if (dist === 0) {
+        send_code(s, lc, ltree); /* send a literal byte */
+        //Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+      } else {
+        /* Here, lc is the match length - MIN_MATCH */
+        code = _length_code[lc];
+        send_code(s, code + LITERALS + 1, ltree); /* send the length code */
+        extra = extra_lbits[code];
+        if (extra !== 0) {
+          lc -= base_length[code];
+          send_bits(s, lc, extra);       /* send the extra length bits */
+        }
+        dist--; /* dist is now the match distance - 1 */
+        code = d_code(dist);
+        //Assert (code < D_CODES, "bad d_code");
+
+        send_code(s, code, dtree);       /* send the distance code */
+        extra = extra_dbits[code];
+        if (extra !== 0) {
+          dist -= base_dist[code];
+          send_bits(s, dist, extra);   /* send the extra distance bits */
+        }
+      } /* literal or match pair ? */
+
+      /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+      //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+      //       "pendingBuf overflow");
+
+    } while (lx < s.last_lit);
+  }
+
+  send_code(s, END_BLOCK, ltree);
+}
+
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+function build_tree(s, desc)
+//    deflate_state *s;
+//    tree_desc *desc; /* the tree descriptor */
+{
+  var tree     = desc.dyn_tree;
+  var stree    = desc.stat_desc.static_tree;
+  var has_stree = desc.stat_desc.has_stree;
+  var elems    = desc.stat_desc.elems;
+  var n, m;          /* iterate over heap elements */
+  var max_code = -1; /* largest code with non zero frequency */
+  var node;          /* new node being created */
+
+  /* Construct the initial heap, with least frequent element in
+   * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+   * heap[0] is not used.
+   */
+  s.heap_len = 0;
+  s.heap_max = HEAP_SIZE;
+
+  for (n = 0; n < elems; n++) {
+    if (tree[n * 2]/*.Freq*/ !== 0) {
+      s.heap[++s.heap_len] = max_code = n;
+      s.depth[n] = 0;
+
+    } else {
+      tree[n * 2 + 1]/*.Len*/ = 0;
+    }
+  }
+
+  /* The pkzip format requires that at least one distance code exists,
+   * and that at least one bit should be sent even if there is only one
+   * possible code. So to avoid special checks later on we force at least
+   * two codes of non zero frequency.
+   */
+  while (s.heap_len < 2) {
+    node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+    tree[node * 2]/*.Freq*/ = 1;
+    s.depth[node] = 0;
+    s.opt_len--;
+
+    if (has_stree) {
+      s.static_len -= stree[node * 2 + 1]/*.Len*/;
+    }
+    /* node is 0 or 1 so it does not have extra bits */
+  }
+  desc.max_code = max_code;
+
+  /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+   * establish sub-heaps of increasing lengths:
+   */
+  for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }
+
+  /* Construct the Huffman tree by repeatedly combining the least two
+   * frequent nodes.
+   */
+  node = elems;              /* next internal node of the tree */
+  do {
+    //pqremove(s, tree, n);  /* n = node of least frequency */
+    /*** pqremove ***/
+    n = s.heap[1/*SMALLEST*/];
+    s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];
+    pqdownheap(s, tree, 1/*SMALLEST*/);
+    /***/
+
+    m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */
+
+    s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */
+    s.heap[--s.heap_max] = m;
+
+    /* Create a new node father of n and m */
+    tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;
+    s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;
+    tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;
+
+    /* and insert the new node in the heap */
+    s.heap[1/*SMALLEST*/] = node++;
+    pqdownheap(s, tree, 1/*SMALLEST*/);
+
+  } while (s.heap_len >= 2);
+
+  s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];
+
+  /* At this point, the fields freq and dad are set. We can now
+   * generate the bit lengths.
+   */
+  gen_bitlen(s, desc);
+
+  /* The field len is now set, we can generate the bit codes */
+  gen_codes(tree, max_code, s.bl_count);
+}
+
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+function scan_tree(s, tree, max_code)
+//    deflate_state *s;
+//    ct_data *tree;   /* the tree to be scanned */
+//    int max_code;    /* and its largest code of non zero frequency */
+{
+  var n;                     /* iterates over all tree elements */
+  var prevlen = -1;          /* last emitted length */
+  var curlen;                /* length of current code */
+
+  var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
+
+  var count = 0;             /* repeat count of the current code */
+  var max_count = 7;         /* max repeat count */
+  var min_count = 4;         /* min repeat count */
+
+  if (nextlen === 0) {
+    max_count = 138;
+    min_count = 3;
+  }
+  tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */
+
+  for (n = 0; n <= max_code; n++) {
+    curlen = nextlen;
+    nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
+
+    if (++count < max_count && curlen === nextlen) {
+      continue;
+
+    } else if (count < min_count) {
+      s.bl_tree[curlen * 2]/*.Freq*/ += count;
+
+    } else if (curlen !== 0) {
+
+      if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }
+      s.bl_tree[REP_3_6 * 2]/*.Freq*/++;
+
+    } else if (count <= 10) {
+      s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++;
+
+    } else {
+      s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++;
+    }
+
+    count = 0;
+    prevlen = curlen;
+
+    if (nextlen === 0) {
+      max_count = 138;
+      min_count = 3;
+
+    } else if (curlen === nextlen) {
+      max_count = 6;
+      min_count = 3;
+
+    } else {
+      max_count = 7;
+      min_count = 4;
+    }
+  }
+}
+
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+function send_tree(s, tree, max_code)
+//    deflate_state *s;
+//    ct_data *tree; /* the tree to be scanned */
+//    int max_code;       /* and its largest code of non zero frequency */
+{
+  var n;                     /* iterates over all tree elements */
+  var prevlen = -1;          /* last emitted length */
+  var curlen;                /* length of current code */
+
+  var nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
+
+  var count = 0;             /* repeat count of the current code */
+  var max_count = 7;         /* max repeat count */
+  var min_count = 4;         /* min repeat count */
+
+  /* tree[max_code+1].Len = -1; */  /* guard already set */
+  if (nextlen === 0) {
+    max_count = 138;
+    min_count = 3;
+  }
+
+  for (n = 0; n <= max_code; n++) {
+    curlen = nextlen;
+    nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
+
+    if (++count < max_count && curlen === nextlen) {
+      continue;
+
+    } else if (count < min_count) {
+      do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);
+
+    } else if (curlen !== 0) {
+      if (curlen !== prevlen) {
+        send_code(s, curlen, s.bl_tree);
+        count--;
+      }
+      //Assert(count >= 3 && count <= 6, " 3_6?");
+      send_code(s, REP_3_6, s.bl_tree);
+      send_bits(s, count - 3, 2);
+
+    } else if (count <= 10) {
+      send_code(s, REPZ_3_10, s.bl_tree);
+      send_bits(s, count - 3, 3);
+
+    } else {
+      send_code(s, REPZ_11_138, s.bl_tree);
+      send_bits(s, count - 11, 7);
+    }
+
+    count = 0;
+    prevlen = curlen;
+    if (nextlen === 0) {
+      max_count = 138;
+      min_count = 3;
+
+    } else if (curlen === nextlen) {
+      max_count = 6;
+      min_count = 3;
+
+    } else {
+      max_count = 7;
+      min_count = 4;
+    }
+  }
+}
+
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+function build_bl_tree(s) {
+  var max_blindex;  /* index of last bit length code of non zero freq */
+
+  /* Determine the bit length frequencies for literal and distance trees */
+  scan_tree(s, s.dyn_ltree, s.l_desc.max_code);
+  scan_tree(s, s.dyn_dtree, s.d_desc.max_code);
+
+  /* Build the bit length tree: */
+  build_tree(s, s.bl_desc);
+  /* opt_len now includes the length of the tree representations, except
+   * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+   */
+
+  /* Determine the number of bit length codes to send. The pkzip format
+   * requires that at least 4 bit length codes be sent. (appnote.txt says
+   * 3 but the actual value used is 4.)
+   */
+  for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
+    if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {
+      break;
+    }
+  }
+  /* Update opt_len to include the bit length tree and counts */
+  s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+  //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+  //        s->opt_len, s->static_len));
+
+  return max_blindex;
+}
+
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+function send_all_trees(s, lcodes, dcodes, blcodes)
+//    deflate_state *s;
+//    int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+  var rank;                    /* index in bl_order */
+
+  //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+  //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+  //        "too many codes");
+  //Tracev((stderr, "\nbl counts: "));
+  send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
+  send_bits(s, dcodes - 1,   5);
+  send_bits(s, blcodes - 4,  4); /* not -3 as stated in appnote.txt */
+  for (rank = 0; rank < blcodes; rank++) {
+    //Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+    send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3);
+  }
+  //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+  send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */
+  //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+  send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */
+  //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ *    a) There are no non-portable control characters belonging to the
+ *       "black list" (0..6, 14..25, 28..31).
+ *    b) There is at least one printable character belonging to the
+ *       "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ *   "gray list" that is ignored in this detection algorithm:
+ *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+function detect_data_type(s) {
+  /* black_mask is the bit mask of black-listed bytes
+   * set bits 0..6, 14..25, and 28..31
+   * 0xf3ffc07f = binary 11110011111111111100000001111111
+   */
+  var black_mask = 0xf3ffc07f;
+  var n;
+
+  /* Check for non-textual ("black-listed") bytes. */
+  for (n = 0; n <= 31; n++, black_mask >>>= 1) {
+    if ((black_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {
+      return Z_BINARY;
+    }
+  }
+
+  /* Check for textual ("white-listed") bytes. */
+  if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||
+      s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {
+    return Z_TEXT;
+  }
+  for (n = 32; n < LITERALS; n++) {
+    if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {
+      return Z_TEXT;
+    }
+  }
+
+  /* There are no "black-listed" or "white-listed" bytes:
+   * this stream either is empty or has tolerated ("gray-listed") bytes only.
+   */
+  return Z_BINARY;
+}
+
+
+var static_init_done = false;
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+function _tr_init(s)
+{
+
+  if (!static_init_done) {
+    tr_static_init();
+    static_init_done = true;
+  }
+
+  s.l_desc  = new TreeDesc(s.dyn_ltree, static_l_desc);
+  s.d_desc  = new TreeDesc(s.dyn_dtree, static_d_desc);
+  s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);
+
+  s.bi_buf = 0;
+  s.bi_valid = 0;
+
+  /* Initialize the first block of the first file: */
+  init_block(s);
+}
+
+
+/* ===========================================================================
+ * Send a stored block
+ */
+function _tr_stored_block(s, buf, stored_len, last)
+//DeflateState *s;
+//charf *buf;       /* input block */
+//ulg stored_len;   /* length of input block */
+//int last;         /* one if this is the last block for a file */
+{
+  send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3);    /* send block type */
+  copy_block(s, buf, stored_len, true); /* with header */
+}
+
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ */
+function _tr_align(s) {
+  send_bits(s, STATIC_TREES << 1, 3);
+  send_code(s, END_BLOCK, static_ltree);
+  bi_flush(s);
+}
+
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+function _tr_flush_block(s, buf, stored_len, last)
+//DeflateState *s;
+//charf *buf;       /* input block, or NULL if too old */
+//ulg stored_len;   /* length of input block */
+//int last;         /* one if this is the last block for a file */
+{
+  var opt_lenb, static_lenb;  /* opt_len and static_len in bytes */
+  var max_blindex = 0;        /* index of last bit length code of non zero freq */
+
+  /* Build the Huffman trees unless a stored block is forced */
+  if (s.level > 0) {
+
+    /* Check if the file is binary or text */
+    if (s.strm.data_type === Z_UNKNOWN) {
+      s.strm.data_type = detect_data_type(s);
+    }
+
+    /* Construct the literal and distance trees */
+    build_tree(s, s.l_desc);
+    // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+    //        s->static_len));
+
+    build_tree(s, s.d_desc);
+    // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+    //        s->static_len));
+    /* At this point, opt_len and static_len are the total bit lengths of
+     * the compressed block data, excluding the tree representations.
+     */
+
+    /* Build the bit length tree for the above two trees, and get the index
+     * in bl_order of the last bit length code to send.
+     */
+    max_blindex = build_bl_tree(s);
+
+    /* Determine the best encoding. Compute the block lengths in bytes. */
+    opt_lenb = (s.opt_len + 3 + 7) >>> 3;
+    static_lenb = (s.static_len + 3 + 7) >>> 3;
+
+    // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+    //        opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+    //        s->last_lit));
+
+    if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }
+
+  } else {
+    // Assert(buf != (char*)0, "lost buf");
+    opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+  }
+
+  if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) {
+    /* 4: two words for the lengths */
+
+    /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+     * Otherwise we can't have processed more than WSIZE input bytes since
+     * the last block flush, because compression would have been
+     * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+     * transform a block into a stored block.
+     */
+    _tr_stored_block(s, buf, stored_len, last);
+
+  } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) {
+
+    send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3);
+    compress_block(s, static_ltree, static_dtree);
+
+  } else {
+    send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3);
+    send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1);
+    compress_block(s, s.dyn_ltree, s.dyn_dtree);
+  }
+  // Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+  /* The above check is made mod 2^32, for files larger than 512 MB
+   * and uLong implemented on 32 bits.
+   */
+  init_block(s);
+
+  if (last) {
+    bi_windup(s);
+  }
+  // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+  //       s->compressed_len-7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+function _tr_tally(s, dist, lc)
+//    deflate_state *s;
+//    unsigned dist;  /* distance of matched string */
+//    unsigned lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+  //var out_length, in_length, dcode;
+
+  s.pending_buf[s.d_buf + s.last_lit * 2]     = (dist >>> 8) & 0xff;
+  s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff;
+
+  s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff;
+  s.last_lit++;
+
+  if (dist === 0) {
+    /* lc is the unmatched char */
+    s.dyn_ltree[lc * 2]/*.Freq*/++;
+  } else {
+    s.matches++;
+    /* Here, lc is the match length - MIN_MATCH */
+    dist--;             /* dist = match distance - 1 */
+    //Assert((ush)dist < (ush)MAX_DIST(s) &&
+    //       (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+    //       (ush)d_code(dist) < (ush)D_CODES,  "_tr_tally: bad match");
+
+    s.dyn_ltree[(_length_code[lc] + LITERALS + 1) * 2]/*.Freq*/++;
+    s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;
+  }
+
+// (!) This block is disabled in zlib defaults,
+// don't enable it for binary compatibility
+
+//#ifdef TRUNCATE_BLOCK
+//  /* Try to guess if it is profitable to stop the current block here */
+//  if ((s.last_lit & 0x1fff) === 0 && s.level > 2) {
+//    /* Compute an upper bound for the compressed length */
+//    out_length = s.last_lit*8;
+//    in_length = s.strstart - s.block_start;
+//
+//    for (dcode = 0; dcode < D_CODES; dcode++) {
+//      out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]);
+//    }
+//    out_length >>>= 3;
+//    //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+//    //       s->last_lit, in_length, out_length,
+//    //       100L - out_length*100L/in_length));
+//    if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) {
+//      return true;
+//    }
+//  }
+//#endif
+
+  return (s.last_lit === s.lit_bufsize - 1);
+  /* We avoid equality with lit_bufsize because of wraparound at 64K
+   * on 16 bit machines and because stored blocks are restricted to
+   * 64K-1 bytes.
+   */
+}
+
+exports._tr_init  = _tr_init;
+exports._tr_stored_block = _tr_stored_block;
+exports._tr_flush_block  = _tr_flush_block;
+exports._tr_tally = _tr_tally;
+exports._tr_align = _tr_align;
+
+},{"../utils/common":26}],38:[function(require,module,exports){
+'use strict';
+
+// (C) 1995-2013 Jean-loup Gailly and Mark Adler
+// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+//   claim that you wrote the original software. If you use this software
+//   in a product, an acknowledgment in the product documentation would be
+//   appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+//   misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+
+function ZStream() {
+  /* next input byte */
+  this.input = null; // JS specific, because we have no pointers
+  this.next_in = 0;
+  /* number of bytes available at input */
+  this.avail_in = 0;
+  /* total number of input bytes read so far */
+  this.total_in = 0;
+  /* next output byte should be put there */
+  this.output = null; // JS specific, because we have no pointers
+  this.next_out = 0;
+  /* remaining free space at output */
+  this.avail_out = 0;
+  /* total number of bytes output so far */
+  this.total_out = 0;
+  /* last error message, NULL if no error */
+  this.msg = ''/*Z_NULL*/;
+  /* not visible by applications */
+  this.state = null;
+  /* best guess about the data type: binary or text */
+  this.data_type = 2/*Z_UNKNOWN*/;
+  /* adler32 value of the uncompressed data */
+  this.adler = 0;
+}
+
+module.exports = ZStream;
+
+},{}],39:[function(require,module,exports){
 (function (process){
 // Copyright Joyent, Inc. and other Node contributors.
 //
@@ -5832,7 +12648,7 @@ var substr = 'ab'.substr(-1) === 'b'
 
 }).call(this,require('_process'))
 
-},{"_process":6}],24:[function(require,module,exports){
+},{"_process":6}],40:[function(require,module,exports){
 'use strict';
 
 module.exports = Pbf;
@@ -6452,7 +13268,7 @@ function writeUtf8(buf, str, pos) {
     return pos;
 }
 
-},{"ieee754":17}],25:[function(require,module,exports){
+},{"ieee754":17}],41:[function(require,module,exports){
 (function (global, factory) {
        typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
        typeof define === 'function' && define.amd ? define(factory) :
@@ -6517,7 +13333,7 @@ return quickselect;
 
 })));
 
-},{}],26:[function(require,module,exports){
+},{}],42:[function(require,module,exports){
 'use strict';
 
 module.exports = rbush;
@@ -7081,7 +13897,7 @@ function multiSelect(arr, left, right, n, compare) {
     }
 }
 
-},{"quickselect":25}],27:[function(require,module,exports){
+},{"quickselect":41}],43:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("./internal/Observable");
@@ -7192,7 +14008,7 @@ exports.NEVER = never_2.NEVER;
 var config_1 = require("./internal/config");
 exports.config = config_1.config;
 
-},{"./internal/AsyncSubject":28,"./internal/BehaviorSubject":29,"./internal/Notification":31,"./internal/Observable":32,"./internal/ReplaySubject":35,"./internal/Scheduler":36,"./internal/Subject":37,"./internal/Subscriber":39,"./internal/Subscription":40,"./internal/config":41,"./internal/observable/ConnectableObservable":42,"./internal/observable/bindCallback":44,"./internal/observable/bindNodeCallback":45,"./internal/observable/combineLatest":46,"./internal/observable/concat":47,"./internal/observable/defer":48,"./internal/observable/empty":49,"./internal/observable/forkJoin":50,"./internal/observable/from":51,"./internal/observable/fromEvent":53,"./internal/observable/fromEventPattern":54,"./internal/observable/generate":58,"./internal/observable/iif":59,"./internal/observable/interval":60,"./internal/observable/merge":61,"./internal/observable/never":62,"./internal/observable/of":63,"./internal/observable/onErrorResumeNext":64,"./internal/observable/pairs":65,"./internal/observable/race":66,"./internal/observable/range":67,"./internal/observable/throwError":69,"./internal/observable/timer":70,"./internal/observable/using":71,"./internal/observable/zip":72,"./internal/operators/groupBy":108,"./internal/scheduler/VirtualTimeScheduler":185,"./internal/scheduler/animationFrame":186,"./internal/scheduler/asap":187,"./internal/scheduler/async":188,"./internal/scheduler/queue":189,"./internal/symbol/observable":191,"./internal/util/ArgumentOutOfRangeError":193,"./internal/util/EmptyError":194,"./internal/util/ObjectUnsubscribedError":196,"./internal/util/TimeoutError":197,"./internal/util/UnsubscriptionError":198,"./internal/util/identity":202,"./internal/util/isObservable":211,"./internal/util/noop":214,"./internal/util/pipe":216}],28:[function(require,module,exports){
+},{"./internal/AsyncSubject":44,"./internal/BehaviorSubject":45,"./internal/Notification":47,"./internal/Observable":48,"./internal/ReplaySubject":51,"./internal/Scheduler":52,"./internal/Subject":53,"./internal/Subscriber":55,"./internal/Subscription":56,"./internal/config":57,"./internal/observable/ConnectableObservable":58,"./internal/observable/bindCallback":60,"./internal/observable/bindNodeCallback":61,"./internal/observable/combineLatest":62,"./internal/observable/concat":63,"./internal/observable/defer":64,"./internal/observable/empty":65,"./internal/observable/forkJoin":66,"./internal/observable/from":67,"./internal/observable/fromEvent":69,"./internal/observable/fromEventPattern":70,"./internal/observable/generate":74,"./internal/observable/iif":75,"./internal/observable/interval":76,"./internal/observable/merge":77,"./internal/observable/never":78,"./internal/observable/of":79,"./internal/observable/onErrorResumeNext":80,"./internal/observable/pairs":81,"./internal/observable/race":82,"./internal/observable/range":83,"./internal/observable/throwError":85,"./internal/observable/timer":86,"./internal/observable/using":87,"./internal/observable/zip":88,"./internal/operators/groupBy":124,"./internal/scheduler/VirtualTimeScheduler":201,"./internal/scheduler/animationFrame":202,"./internal/scheduler/asap":203,"./internal/scheduler/async":204,"./internal/scheduler/queue":205,"./internal/symbol/observable":207,"./internal/util/ArgumentOutOfRangeError":209,"./internal/util/EmptyError":210,"./internal/util/ObjectUnsubscribedError":212,"./internal/util/TimeoutError":213,"./internal/util/UnsubscriptionError":214,"./internal/util/identity":218,"./internal/util/isObservable":227,"./internal/util/noop":230,"./internal/util/pipe":232}],44:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -7253,7 +14069,7 @@ var AsyncSubject = (function (_super) {
 }(Subject_1.Subject));
 exports.AsyncSubject = AsyncSubject;
 
-},{"./Subject":37,"./Subscription":40}],29:[function(require,module,exports){
+},{"./Subject":53,"./Subscription":56}],45:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -7310,7 +14126,7 @@ var BehaviorSubject = (function (_super) {
 }(Subject_1.Subject));
 exports.BehaviorSubject = BehaviorSubject;
 
-},{"./Subject":37,"./util/ObjectUnsubscribedError":196}],30:[function(require,module,exports){
+},{"./Subject":53,"./util/ObjectUnsubscribedError":212}],46:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -7352,7 +14168,7 @@ var InnerSubscriber = (function (_super) {
 }(Subscriber_1.Subscriber));
 exports.InnerSubscriber = InnerSubscriber;
 
-},{"./Subscriber":39}],31:[function(require,module,exports){
+},{"./Subscriber":55}],47:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var empty_1 = require("./observable/empty");
@@ -7424,7 +14240,7 @@ var Notification = (function () {
 }());
 exports.Notification = Notification;
 
-},{"./observable/empty":49,"./observable/of":63,"./observable/throwError":69}],32:[function(require,module,exports){
+},{"./observable/empty":65,"./observable/of":79,"./observable/throwError":85}],48:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var canReportError_1 = require("./util/canReportError");
@@ -7542,7 +14358,7 @@ function getPromiseCtor(promiseCtor) {
     return promiseCtor;
 }
 
-},{"../internal/symbol/observable":191,"./config":41,"./util/canReportError":199,"./util/pipe":216,"./util/toSubscriber":223}],33:[function(require,module,exports){
+},{"../internal/symbol/observable":207,"./config":57,"./util/canReportError":215,"./util/pipe":232,"./util/toSubscriber":239}],49:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var config_1 = require("./config");
@@ -7561,7 +14377,7 @@ exports.empty = {
     complete: function () { }
 };
 
-},{"./config":41,"./util/hostReportError":201}],34:[function(require,module,exports){
+},{"./config":57,"./util/hostReportError":217}],50:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -7596,7 +14412,7 @@ var OuterSubscriber = (function (_super) {
 }(Subscriber_1.Subscriber));
 exports.OuterSubscriber = OuterSubscriber;
 
-},{"./Subscriber":39}],35:[function(require,module,exports){
+},{"./Subscriber":55}],51:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -7723,7 +14539,7 @@ var ReplayEvent = (function () {
     return ReplayEvent;
 }());
 
-},{"./Subject":37,"./SubjectSubscription":38,"./Subscription":40,"./operators/observeOn":123,"./scheduler/queue":189,"./util/ObjectUnsubscribedError":196}],36:[function(require,module,exports){
+},{"./Subject":53,"./SubjectSubscription":54,"./Subscription":56,"./operators/observeOn":139,"./scheduler/queue":205,"./util/ObjectUnsubscribedError":212}],52:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Scheduler = (function () {
@@ -7741,7 +14557,7 @@ var Scheduler = (function () {
 }());
 exports.Scheduler = Scheduler;
 
-},{}],37:[function(require,module,exports){
+},{}],53:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -7913,7 +14729,7 @@ var AnonymousSubject = (function (_super) {
 }(Subject));
 exports.AnonymousSubject = AnonymousSubject;
 
-},{"../internal/symbol/rxSubscriber":192,"./Observable":32,"./SubjectSubscription":38,"./Subscriber":39,"./Subscription":40,"./util/ObjectUnsubscribedError":196}],38:[function(require,module,exports){
+},{"../internal/symbol/rxSubscriber":208,"./Observable":48,"./SubjectSubscription":54,"./Subscriber":55,"./Subscription":56,"./util/ObjectUnsubscribedError":212}],54:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -7959,7 +14775,7 @@ var SubjectSubscription = (function (_super) {
 }(Subscription_1.Subscription));
 exports.SubjectSubscription = SubjectSubscription;
 
-},{"./Subscription":40}],39:[function(require,module,exports){
+},{"./Subscription":56}],55:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -8210,7 +15026,7 @@ var SafeSubscriber = (function (_super) {
 }(Subscriber));
 exports.SafeSubscriber = SafeSubscriber;
 
-},{"../internal/symbol/rxSubscriber":192,"./Observer":33,"./Subscription":40,"./config":41,"./util/hostReportError":201,"./util/isFunction":206}],40:[function(require,module,exports){
+},{"../internal/symbol/rxSubscriber":208,"./Observer":49,"./Subscription":56,"./config":57,"./util/hostReportError":217,"./util/isFunction":222}],56:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var isArray_1 = require("./util/isArray");
@@ -8344,7 +15160,7 @@ function flattenUnsubscriptionErrors(errors) {
     return errors.reduce(function (errs, err) { return errs.concat((err instanceof UnsubscriptionError_1.UnsubscriptionError) ? err.errors : err); }, []);
 }
 
-},{"./util/UnsubscriptionError":198,"./util/errorObject":200,"./util/isArray":203,"./util/isFunction":206,"./util/isObject":210,"./util/tryCatch":224}],41:[function(require,module,exports){
+},{"./util/UnsubscriptionError":214,"./util/errorObject":216,"./util/isArray":219,"./util/isFunction":222,"./util/isObject":226,"./util/tryCatch":240}],57:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var _enable_super_gross_mode_that_will_cause_bad_things = false;
@@ -8365,7 +15181,7 @@ exports.config = {
     },
 };
 
-},{}],42:[function(require,module,exports){
+},{}],58:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -8522,7 +15338,7 @@ var RefCountSubscriber = (function (_super) {
     return RefCountSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Observable":32,"../Subject":37,"../Subscriber":39,"../Subscription":40,"../operators/refCount":134}],43:[function(require,module,exports){
+},{"../Observable":48,"../Subject":53,"../Subscriber":55,"../Subscription":56,"../operators/refCount":150}],59:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -8579,7 +15395,7 @@ var SubscribeOnObservable = (function (_super) {
 }(Observable_1.Observable));
 exports.SubscribeOnObservable = SubscribeOnObservable;
 
-},{"../Observable":32,"../scheduler/asap":187,"../util/isNumeric":209}],44:[function(require,module,exports){
+},{"../Observable":48,"../scheduler/asap":203,"../util/isNumeric":225}],60:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -8687,7 +15503,7 @@ function dispatchError(state) {
     subject.error(err);
 }
 
-},{"../AsyncSubject":28,"../Observable":32,"../operators/map":112,"../util/canReportError":199,"../util/isArray":203,"../util/isScheduler":213}],45:[function(require,module,exports){
+},{"../AsyncSubject":44,"../Observable":48,"../operators/map":128,"../util/canReportError":215,"../util/isArray":219,"../util/isScheduler":229}],61:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -8803,7 +15619,7 @@ function dispatchError(arg) {
     subject.error(err);
 }
 
-},{"../AsyncSubject":28,"../Observable":32,"../operators/map":112,"../util/canReportError":199,"../util/isArray":203,"../util/isScheduler":213}],46:[function(require,module,exports){
+},{"../AsyncSubject":44,"../Observable":48,"../operators/map":128,"../util/canReportError":215,"../util/isArray":219,"../util/isScheduler":229}],62:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -8919,7 +15735,7 @@ var CombineLatestSubscriber = (function (_super) {
 }(OuterSubscriber_1.OuterSubscriber));
 exports.CombineLatestSubscriber = CombineLatestSubscriber;
 
-},{"../OuterSubscriber":34,"../util/isArray":203,"../util/isScheduler":213,"../util/subscribeToResult":222,"./fromArray":52}],47:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/isArray":219,"../util/isScheduler":229,"../util/subscribeToResult":238,"./fromArray":68}],63:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var isScheduler_1 = require("../util/isScheduler");
@@ -8938,7 +15754,7 @@ function concat() {
 }
 exports.concat = concat;
 
-},{"../operators/concatAll":84,"../util/isScheduler":213,"./from":51,"./of":63}],48:[function(require,module,exports){
+},{"../operators/concatAll":100,"../util/isScheduler":229,"./from":67,"./of":79}],64:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -8960,7 +15776,7 @@ function defer(observableFactory) {
 }
 exports.defer = defer;
 
-},{"../Observable":32,"./empty":49,"./from":51}],49:[function(require,module,exports){
+},{"../Observable":48,"./empty":65,"./from":67}],65:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -8974,7 +15790,7 @@ function emptyScheduled(scheduler) {
 }
 exports.emptyScheduled = emptyScheduled;
 
-},{"../Observable":32}],50:[function(require,module,exports){
+},{"../Observable":48}],66:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -9063,7 +15879,7 @@ var ForkJoinSubscriber = (function (_super) {
     return ForkJoinSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../Observable":32,"../OuterSubscriber":34,"../operators/map":112,"../util/isArray":203,"../util/subscribeToResult":222,"./empty":49}],51:[function(require,module,exports){
+},{"../Observable":48,"../OuterSubscriber":50,"../operators/map":128,"../util/isArray":219,"../util/subscribeToResult":238,"./empty":65}],67:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9101,7 +15917,7 @@ function from(input, scheduler) {
 }
 exports.from = from;
 
-},{"../Observable":32,"../util/isArrayLike":204,"../util/isInteropObservable":207,"../util/isIterable":208,"../util/isPromise":212,"../util/subscribeTo":217,"./fromArray":52,"./fromIterable":55,"./fromObservable":56,"./fromPromise":57}],52:[function(require,module,exports){
+},{"../Observable":48,"../util/isArrayLike":220,"../util/isInteropObservable":223,"../util/isIterable":224,"../util/isPromise":228,"../util/subscribeTo":233,"./fromArray":68,"./fromIterable":71,"./fromObservable":72,"./fromPromise":73}],68:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9131,7 +15947,7 @@ function fromArray(input, scheduler) {
 }
 exports.fromArray = fromArray;
 
-},{"../Observable":32,"../Subscription":40,"../util/subscribeToArray":218}],53:[function(require,module,exports){
+},{"../Observable":48,"../Subscription":56,"../util/subscribeToArray":234}],69:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9197,7 +16013,7 @@ function isEventTarget(sourceObj) {
     return sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function';
 }
 
-},{"../Observable":32,"../operators/map":112,"../util/isArray":203,"../util/isFunction":206}],54:[function(require,module,exports){
+},{"../Observable":48,"../operators/map":128,"../util/isArray":219,"../util/isFunction":222}],70:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9232,7 +16048,7 @@ function fromEventPattern(addHandler, removeHandler, resultSelector) {
 }
 exports.fromEventPattern = fromEventPattern;
 
-},{"../Observable":32,"../operators/map":112,"../util/isArray":203,"../util/isFunction":206}],55:[function(require,module,exports){
+},{"../Observable":48,"../operators/map":128,"../util/isArray":219,"../util/isFunction":222}],71:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9287,7 +16103,7 @@ function fromIterable(input, scheduler) {
 }
 exports.fromIterable = fromIterable;
 
-},{"../Observable":32,"../Subscription":40,"../symbol/iterator":190,"../util/subscribeToIterable":219}],56:[function(require,module,exports){
+},{"../Observable":48,"../Subscription":56,"../symbol/iterator":206,"../util/subscribeToIterable":235}],72:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9315,7 +16131,7 @@ function fromObservable(input, scheduler) {
 }
 exports.fromObservable = fromObservable;
 
-},{"../Observable":32,"../Subscription":40,"../symbol/observable":191,"../util/subscribeToObservable":220}],57:[function(require,module,exports){
+},{"../Observable":48,"../Subscription":56,"../symbol/observable":207,"../util/subscribeToObservable":236}],73:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9342,7 +16158,7 @@ function fromPromise(input, scheduler) {
 }
 exports.fromPromise = fromPromise;
 
-},{"../Observable":32,"../Subscription":40,"../util/subscribeToPromise":221}],58:[function(require,module,exports){
+},{"../Observable":48,"../Subscription":56,"../util/subscribeToPromise":237}],74:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9470,7 +16286,7 @@ function dispatch(state) {
     return this.schedule(state);
 }
 
-},{"../Observable":32,"../util/identity":202,"../util/isScheduler":213}],59:[function(require,module,exports){
+},{"../Observable":48,"../util/identity":218,"../util/isScheduler":229}],75:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var defer_1 = require("./defer");
@@ -9482,7 +16298,7 @@ function iif(condition, trueResult, falseResult) {
 }
 exports.iif = iif;
 
-},{"./defer":48,"./empty":49}],60:[function(require,module,exports){
+},{"./defer":64,"./empty":65}],76:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9509,7 +16325,7 @@ function dispatch(state) {
     this.schedule({ subscriber: subscriber, counter: counter + 1, period: period }, period);
 }
 
-},{"../Observable":32,"../scheduler/async":188,"../util/isNumeric":209}],61:[function(require,module,exports){
+},{"../Observable":48,"../scheduler/async":204,"../util/isNumeric":225}],77:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9540,7 +16356,7 @@ function merge() {
 }
 exports.merge = merge;
 
-},{"../Observable":32,"../operators/mergeAll":117,"../util/isScheduler":213,"./fromArray":52}],62:[function(require,module,exports){
+},{"../Observable":48,"../operators/mergeAll":133,"../util/isScheduler":229,"./fromArray":68}],78:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9551,7 +16367,7 @@ function never() {
 }
 exports.never = never;
 
-},{"../Observable":32,"../util/noop":214}],63:[function(require,module,exports){
+},{"../Observable":48,"../util/noop":230}],79:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var isScheduler_1 = require("../util/isScheduler");
@@ -9581,7 +16397,7 @@ function of() {
 }
 exports.of = of;
 
-},{"../util/isScheduler":213,"./empty":49,"./fromArray":52,"./scalar":68}],64:[function(require,module,exports){
+},{"../util/isScheduler":229,"./empty":65,"./fromArray":68,"./scalar":84}],80:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9611,7 +16427,7 @@ function onErrorResumeNext() {
 }
 exports.onErrorResumeNext = onErrorResumeNext;
 
-},{"../Observable":32,"../util/isArray":203,"./empty":49,"./from":51}],65:[function(require,module,exports){
+},{"../Observable":48,"../util/isArray":219,"./empty":65,"./from":67}],81:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9654,7 +16470,7 @@ function dispatch(state) {
 }
 exports.dispatch = dispatch;
 
-},{"../Observable":32,"../Subscription":40}],66:[function(require,module,exports){
+},{"../Observable":48,"../Subscription":56}],82:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -9747,7 +16563,7 @@ var RaceSubscriber = (function (_super) {
 }(OuterSubscriber_1.OuterSubscriber));
 exports.RaceSubscriber = RaceSubscriber;
 
-},{"../OuterSubscriber":34,"../util/isArray":203,"../util/subscribeToResult":222,"./fromArray":52}],67:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/isArray":219,"../util/subscribeToResult":238,"./fromArray":68}],83:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9794,7 +16610,7 @@ function dispatch(state) {
 }
 exports.dispatch = dispatch;
 
-},{"../Observable":32}],68:[function(require,module,exports){
+},{"../Observable":48}],84:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9809,7 +16625,7 @@ function scalar(value) {
 }
 exports.scalar = scalar;
 
-},{"../Observable":32}],69:[function(require,module,exports){
+},{"../Observable":48}],85:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9827,7 +16643,7 @@ function dispatch(_a) {
     subscriber.error(error);
 }
 
-},{"../Observable":32}],70:[function(require,module,exports){
+},{"../Observable":48}],86:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9869,7 +16685,7 @@ function dispatch(state) {
     this.schedule(state, period);
 }
 
-},{"../Observable":32,"../scheduler/async":188,"../util/isNumeric":209,"../util/isScheduler":213}],71:[function(require,module,exports){
+},{"../Observable":48,"../scheduler/async":204,"../util/isNumeric":225,"../util/isScheduler":229}],87:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -9905,7 +16721,7 @@ function using(resourceFactory, observableFactory) {
 }
 exports.using = using;
 
-},{"../Observable":32,"./empty":49,"./from":51}],72:[function(require,module,exports){
+},{"../Observable":48,"./empty":65,"./from":67}],88:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -10136,7 +16952,7 @@ var ZipBufferIterator = (function (_super) {
     return ZipBufferIterator;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../../internal/symbol/iterator":190,"../OuterSubscriber":34,"../Subscriber":39,"../util/isArray":203,"../util/subscribeToResult":222,"./fromArray":52}],73:[function(require,module,exports){
+},{"../../internal/symbol/iterator":206,"../OuterSubscriber":50,"../Subscriber":55,"../util/isArray":219,"../util/subscribeToResult":238,"./fromArray":68}],89:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -10220,7 +17036,7 @@ var AuditSubscriber = (function (_super) {
     return AuditSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../util/errorObject":200,"../util/subscribeToResult":222,"../util/tryCatch":224}],74:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/errorObject":216,"../util/subscribeToResult":238,"../util/tryCatch":240}],90:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var async_1 = require("../scheduler/async");
@@ -10232,7 +17048,7 @@ function auditTime(duration, scheduler) {
 }
 exports.auditTime = auditTime;
 
-},{"../observable/timer":70,"../scheduler/async":188,"./audit":73}],75:[function(require,module,exports){
+},{"../observable/timer":86,"../scheduler/async":204,"./audit":89}],91:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -10284,7 +17100,7 @@ var BufferSubscriber = (function (_super) {
     return BufferSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../util/subscribeToResult":222}],76:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/subscribeToResult":238}],92:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -10387,7 +17203,7 @@ var BufferSkipCountSubscriber = (function (_super) {
     return BufferSkipCountSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],77:[function(require,module,exports){
+},{"../Subscriber":55}],93:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -10550,7 +17366,7 @@ function dispatchBufferClose(arg) {
     subscriber.closeContext(context);
 }
 
-},{"../Subscriber":39,"../scheduler/async":188,"../util/isScheduler":213}],78:[function(require,module,exports){
+},{"../Subscriber":55,"../scheduler/async":204,"../util/isScheduler":229}],94:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -10672,7 +17488,7 @@ var BufferToggleSubscriber = (function (_super) {
     return BufferToggleSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../Subscription":40,"../util/subscribeToResult":222}],79:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../Subscription":56,"../util/subscribeToResult":238}],95:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -10769,7 +17585,7 @@ var BufferWhenSubscriber = (function (_super) {
     return BufferWhenSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../Subscription":40,"../util/errorObject":200,"../util/subscribeToResult":222,"../util/tryCatch":224}],80:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../Subscription":56,"../util/errorObject":216,"../util/subscribeToResult":238,"../util/tryCatch":240}],96:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -10832,7 +17648,7 @@ var CatchSubscriber = (function (_super) {
     return CatchSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../InnerSubscriber":30,"../OuterSubscriber":34,"../util/subscribeToResult":222}],81:[function(require,module,exports){
+},{"../InnerSubscriber":46,"../OuterSubscriber":50,"../util/subscribeToResult":238}],97:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var combineLatest_1 = require("../observable/combineLatest");
@@ -10841,7 +17657,7 @@ function combineAll(project) {
 }
 exports.combineAll = combineAll;
 
-},{"../observable/combineLatest":46}],82:[function(require,module,exports){
+},{"../observable/combineLatest":62}],98:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var isArray_1 = require("../util/isArray");
@@ -10864,7 +17680,7 @@ function combineLatest() {
 }
 exports.combineLatest = combineLatest;
 
-},{"../observable/combineLatest":46,"../observable/from":51,"../util/isArray":203}],83:[function(require,module,exports){
+},{"../observable/combineLatest":62,"../observable/from":67,"../util/isArray":219}],99:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var concat_1 = require("../observable/concat");
@@ -10877,7 +17693,7 @@ function concat() {
 }
 exports.concat = concat;
 
-},{"../observable/concat":47}],84:[function(require,module,exports){
+},{"../observable/concat":63}],100:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var mergeAll_1 = require("./mergeAll");
@@ -10886,7 +17702,7 @@ function concatAll() {
 }
 exports.concatAll = concatAll;
 
-},{"./mergeAll":117}],85:[function(require,module,exports){
+},{"./mergeAll":133}],101:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var mergeMap_1 = require("./mergeMap");
@@ -10895,7 +17711,7 @@ function concatMap(project, resultSelector) {
 }
 exports.concatMap = concatMap;
 
-},{"./mergeMap":118}],86:[function(require,module,exports){
+},{"./mergeMap":134}],102:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var concatMap_1 = require("./concatMap");
@@ -10904,7 +17720,7 @@ function concatMapTo(innerObservable, resultSelector) {
 }
 exports.concatMapTo = concatMapTo;
 
-},{"./concatMap":85}],87:[function(require,module,exports){
+},{"./concatMap":101}],103:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -10973,7 +17789,7 @@ var CountSubscriber = (function (_super) {
     return CountSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],88:[function(require,module,exports){
+},{"../Subscriber":55}],104:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11064,7 +17880,7 @@ var DebounceSubscriber = (function (_super) {
     return DebounceSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../util/subscribeToResult":222}],89:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/subscribeToResult":238}],105:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11141,7 +17957,7 @@ function dispatchNext(subscriber) {
     subscriber.debouncedNext();
 }
 
-},{"../Subscriber":39,"../scheduler/async":188}],90:[function(require,module,exports){
+},{"../Subscriber":55,"../scheduler/async":204}],106:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11193,7 +18009,7 @@ var DefaultIfEmptySubscriber = (function (_super) {
     return DefaultIfEmptySubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],91:[function(require,module,exports){
+},{"../Subscriber":55}],107:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11299,7 +18115,7 @@ var DelayMessage = (function () {
     return DelayMessage;
 }());
 
-},{"../Notification":31,"../Subscriber":39,"../scheduler/async":188,"../util/isDate":205}],92:[function(require,module,exports){
+},{"../Notification":47,"../Subscriber":55,"../scheduler/async":204,"../util/isDate":221}],108:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11446,7 +18262,7 @@ var SubscriptionDelaySubscriber = (function (_super) {
     return SubscriptionDelaySubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Observable":32,"../OuterSubscriber":34,"../Subscriber":39,"../util/subscribeToResult":222}],93:[function(require,module,exports){
+},{"../Observable":48,"../OuterSubscriber":50,"../Subscriber":55,"../util/subscribeToResult":238}],109:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11488,7 +18304,7 @@ var DeMaterializeSubscriber = (function (_super) {
     return DeMaterializeSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],94:[function(require,module,exports){
+},{"../Subscriber":55}],110:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11568,7 +18384,7 @@ var DistinctSubscriber = (function (_super) {
 }(OuterSubscriber_1.OuterSubscriber));
 exports.DistinctSubscriber = DistinctSubscriber;
 
-},{"../OuterSubscriber":34,"../util/subscribeToResult":222}],95:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/subscribeToResult":238}],111:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11642,7 +18458,7 @@ var DistinctUntilChangedSubscriber = (function (_super) {
     return DistinctUntilChangedSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39,"../util/errorObject":200,"../util/tryCatch":224}],96:[function(require,module,exports){
+},{"../Subscriber":55,"../util/errorObject":216,"../util/tryCatch":240}],112:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var distinctUntilChanged_1 = require("./distinctUntilChanged");
@@ -11651,7 +18467,7 @@ function distinctUntilKeyChanged(key, compare) {
 }
 exports.distinctUntilKeyChanged = distinctUntilKeyChanged;
 
-},{"./distinctUntilChanged":95}],97:[function(require,module,exports){
+},{"./distinctUntilChanged":111}],113:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var ArgumentOutOfRangeError_1 = require("../util/ArgumentOutOfRangeError");
@@ -11670,7 +18486,7 @@ function elementAt(index, defaultValue) {
 }
 exports.elementAt = elementAt;
 
-},{"../util/ArgumentOutOfRangeError":193,"./defaultIfEmpty":90,"./filter":103,"./take":155,"./throwIfEmpty":162}],98:[function(require,module,exports){
+},{"../util/ArgumentOutOfRangeError":209,"./defaultIfEmpty":106,"./filter":119,"./take":171,"./throwIfEmpty":178}],114:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var fromArray_1 = require("../observable/fromArray");
@@ -11705,7 +18521,7 @@ function endWith() {
 }
 exports.endWith = endWith;
 
-},{"../observable/concat":47,"../observable/empty":49,"../observable/fromArray":52,"../observable/scalar":68,"../util/isScheduler":213}],99:[function(require,module,exports){
+},{"../observable/concat":63,"../observable/empty":65,"../observable/fromArray":68,"../observable/scalar":84,"../util/isScheduler":229}],115:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11771,7 +18587,7 @@ var EverySubscriber = (function (_super) {
     return EverySubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],100:[function(require,module,exports){
+},{"../Subscriber":55}],116:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11831,7 +18647,7 @@ var SwitchFirstSubscriber = (function (_super) {
     return SwitchFirstSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../util/subscribeToResult":222}],101:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/subscribeToResult":238}],117:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -11928,7 +18744,7 @@ var ExhaustMapSubscriber = (function (_super) {
     return ExhaustMapSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../InnerSubscriber":30,"../OuterSubscriber":34,"../observable/from":51,"../util/subscribeToResult":222,"./map":112}],102:[function(require,module,exports){
+},{"../InnerSubscriber":46,"../OuterSubscriber":50,"../observable/from":67,"../util/subscribeToResult":238,"./map":128}],118:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12043,7 +18859,7 @@ var ExpandSubscriber = (function (_super) {
 }(OuterSubscriber_1.OuterSubscriber));
 exports.ExpandSubscriber = ExpandSubscriber;
 
-},{"../OuterSubscriber":34,"../util/errorObject":200,"../util/subscribeToResult":222,"../util/tryCatch":224}],103:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/errorObject":216,"../util/subscribeToResult":238,"../util/tryCatch":240}],119:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12101,7 +18917,7 @@ var FilterSubscriber = (function (_super) {
     return FilterSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],104:[function(require,module,exports){
+},{"../Subscriber":55}],120:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12142,7 +18958,7 @@ var FinallySubscriber = (function (_super) {
     return FinallySubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39,"../Subscription":40}],105:[function(require,module,exports){
+},{"../Subscriber":55,"../Subscription":56}],121:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12216,7 +19032,7 @@ var FindValueSubscriber = (function (_super) {
 }(Subscriber_1.Subscriber));
 exports.FindValueSubscriber = FindValueSubscriber;
 
-},{"../Subscriber":39}],106:[function(require,module,exports){
+},{"../Subscriber":55}],122:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var find_1 = require("../operators/find");
@@ -12225,7 +19041,7 @@ function findIndex(predicate, thisArg) {
 }
 exports.findIndex = findIndex;
 
-},{"../operators/find":105}],107:[function(require,module,exports){
+},{"../operators/find":121}],123:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var EmptyError_1 = require("../util/EmptyError");
@@ -12240,7 +19056,7 @@ function first(predicate, defaultValue) {
 }
 exports.first = first;
 
-},{"../util/EmptyError":194,"../util/identity":202,"./defaultIfEmpty":90,"./filter":103,"./take":155,"./throwIfEmpty":162}],108:[function(require,module,exports){
+},{"../util/EmptyError":210,"../util/identity":218,"./defaultIfEmpty":106,"./filter":119,"./take":171,"./throwIfEmpty":178}],124:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12437,7 +19253,7 @@ var InnerRefCountSubscription = (function (_super) {
     return InnerRefCountSubscription;
 }(Subscription_1.Subscription));
 
-},{"../Observable":32,"../Subject":37,"../Subscriber":39,"../Subscription":40}],109:[function(require,module,exports){
+},{"../Observable":48,"../Subject":53,"../Subscriber":55,"../Subscription":56}],125:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12478,7 +19294,7 @@ var IgnoreElementsSubscriber = (function (_super) {
     return IgnoreElementsSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],110:[function(require,module,exports){
+},{"../Subscriber":55}],126:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12526,7 +19342,7 @@ var IsEmptySubscriber = (function (_super) {
     return IsEmptySubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],111:[function(require,module,exports){
+},{"../Subscriber":55}],127:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var EmptyError_1 = require("../util/EmptyError");
@@ -12541,7 +19357,7 @@ function last(predicate, defaultValue) {
 }
 exports.last = last;
 
-},{"../util/EmptyError":194,"../util/identity":202,"./defaultIfEmpty":90,"./filter":103,"./takeLast":156,"./throwIfEmpty":162}],112:[function(require,module,exports){
+},{"../util/EmptyError":210,"../util/identity":218,"./defaultIfEmpty":106,"./filter":119,"./takeLast":172,"./throwIfEmpty":178}],128:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12601,7 +19417,7 @@ var MapSubscriber = (function (_super) {
     return MapSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],113:[function(require,module,exports){
+},{"../Subscriber":55}],129:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12644,7 +19460,7 @@ var MapToSubscriber = (function (_super) {
     return MapToSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],114:[function(require,module,exports){
+},{"../Subscriber":55}],130:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12697,7 +19513,7 @@ var MaterializeSubscriber = (function (_super) {
     return MaterializeSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Notification":31,"../Subscriber":39}],115:[function(require,module,exports){
+},{"../Notification":47,"../Subscriber":55}],131:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var reduce_1 = require("./reduce");
@@ -12709,7 +19525,7 @@ function max(comparer) {
 }
 exports.max = max;
 
-},{"./reduce":133}],116:[function(require,module,exports){
+},{"./reduce":149}],132:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var merge_1 = require("../observable/merge");
@@ -12722,7 +19538,7 @@ function merge() {
 }
 exports.merge = merge;
 
-},{"../observable/merge":61}],117:[function(require,module,exports){
+},{"../observable/merge":77}],133:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var mergeMap_1 = require("./mergeMap");
@@ -12733,7 +19549,7 @@ function mergeAll(concurrent) {
 }
 exports.mergeAll = mergeAll;
 
-},{"../util/identity":202,"./mergeMap":118}],118:[function(require,module,exports){
+},{"../util/identity":218,"./mergeMap":134}],134:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12842,7 +19658,7 @@ var MergeMapSubscriber = (function (_super) {
 }(OuterSubscriber_1.OuterSubscriber));
 exports.MergeMapSubscriber = MergeMapSubscriber;
 
-},{"../InnerSubscriber":30,"../OuterSubscriber":34,"../observable/from":51,"../util/subscribeToResult":222,"./map":112}],119:[function(require,module,exports){
+},{"../InnerSubscriber":46,"../OuterSubscriber":50,"../observable/from":67,"../util/subscribeToResult":238,"./map":128}],135:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var mergeMap_1 = require("./mergeMap");
@@ -12858,7 +19674,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) {
 }
 exports.mergeMapTo = mergeMapTo;
 
-},{"./mergeMap":118}],120:[function(require,module,exports){
+},{"./mergeMap":134}],136:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -12968,7 +19784,7 @@ var MergeScanSubscriber = (function (_super) {
 }(OuterSubscriber_1.OuterSubscriber));
 exports.MergeScanSubscriber = MergeScanSubscriber;
 
-},{"../InnerSubscriber":30,"../OuterSubscriber":34,"../util/errorObject":200,"../util/subscribeToResult":222,"../util/tryCatch":224}],121:[function(require,module,exports){
+},{"../InnerSubscriber":46,"../OuterSubscriber":50,"../util/errorObject":216,"../util/subscribeToResult":238,"../util/tryCatch":240}],137:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var reduce_1 = require("./reduce");
@@ -12980,7 +19796,7 @@ function min(comparer) {
 }
 exports.min = min;
 
-},{"./reduce":133}],122:[function(require,module,exports){
+},{"./reduce":149}],138:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var ConnectableObservable_1 = require("../observable/ConnectableObservable");
@@ -13021,7 +19837,7 @@ var MulticastOperator = (function () {
 }());
 exports.MulticastOperator = MulticastOperator;
 
-},{"../observable/ConnectableObservable":42}],123:[function(require,module,exports){
+},{"../observable/ConnectableObservable":58}],139:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13099,7 +19915,7 @@ var ObserveOnMessage = (function () {
 }());
 exports.ObserveOnMessage = ObserveOnMessage;
 
-},{"../Notification":31,"../Subscriber":39}],124:[function(require,module,exports){
+},{"../Notification":47,"../Subscriber":55}],140:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13190,7 +20006,7 @@ var OnErrorResumeNextSubscriber = (function (_super) {
     return OnErrorResumeNextSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../InnerSubscriber":30,"../OuterSubscriber":34,"../observable/from":51,"../util/isArray":203,"../util/subscribeToResult":222}],125:[function(require,module,exports){
+},{"../InnerSubscriber":46,"../OuterSubscriber":50,"../observable/from":67,"../util/isArray":219,"../util/subscribeToResult":238}],141:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13238,7 +20054,7 @@ var PairwiseSubscriber = (function (_super) {
     return PairwiseSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],126:[function(require,module,exports){
+},{"../Subscriber":55}],142:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var not_1 = require("../util/not");
@@ -13251,7 +20067,7 @@ function partition(predicate, thisArg) {
 }
 exports.partition = partition;
 
-},{"../util/not":215,"./filter":103}],127:[function(require,module,exports){
+},{"../util/not":231,"./filter":119}],143:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var map_1 = require("./map");
@@ -13284,7 +20100,7 @@ function plucker(props, length) {
     return mapper;
 }
 
-},{"./map":112}],128:[function(require,module,exports){
+},{"./map":128}],144:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Subject_1 = require("../Subject");
@@ -13296,7 +20112,7 @@ function publish(selector) {
 }
 exports.publish = publish;
 
-},{"../Subject":37,"./multicast":122}],129:[function(require,module,exports){
+},{"../Subject":53,"./multicast":138}],145:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var BehaviorSubject_1 = require("../BehaviorSubject");
@@ -13306,7 +20122,7 @@ function publishBehavior(value) {
 }
 exports.publishBehavior = publishBehavior;
 
-},{"../BehaviorSubject":29,"./multicast":122}],130:[function(require,module,exports){
+},{"../BehaviorSubject":45,"./multicast":138}],146:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var AsyncSubject_1 = require("../AsyncSubject");
@@ -13316,7 +20132,7 @@ function publishLast() {
 }
 exports.publishLast = publishLast;
 
-},{"../AsyncSubject":28,"./multicast":122}],131:[function(require,module,exports){
+},{"../AsyncSubject":44,"./multicast":138}],147:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var ReplaySubject_1 = require("../ReplaySubject");
@@ -13331,7 +20147,7 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) {
 }
 exports.publishReplay = publishReplay;
 
-},{"../ReplaySubject":35,"./multicast":122}],132:[function(require,module,exports){
+},{"../ReplaySubject":51,"./multicast":138}],148:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var isArray_1 = require("../util/isArray");
@@ -13350,7 +20166,7 @@ function race() {
 }
 exports.race = race;
 
-},{"../observable/race":66,"../util/isArray":203}],133:[function(require,module,exports){
+},{"../observable/race":82,"../util/isArray":219}],149:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var scan_1 = require("./scan");
@@ -13369,7 +20185,7 @@ function reduce(accumulator, seed) {
 }
 exports.reduce = reduce;
 
-},{"../util/pipe":216,"./defaultIfEmpty":90,"./scan":141,"./takeLast":156}],134:[function(require,module,exports){
+},{"../util/pipe":232,"./defaultIfEmpty":106,"./scan":157,"./takeLast":172}],150:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13442,7 +20258,7 @@ var RefCountSubscriber = (function (_super) {
     return RefCountSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],135:[function(require,module,exports){
+},{"../Subscriber":55}],151:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13508,7 +20324,7 @@ var RepeatSubscriber = (function (_super) {
     return RepeatSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39,"../observable/empty":49}],136:[function(require,module,exports){
+},{"../Subscriber":55,"../observable/empty":65}],152:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13604,7 +20420,7 @@ var RepeatWhenSubscriber = (function (_super) {
     return RepeatWhenSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../Subject":37,"../util/errorObject":200,"../util/subscribeToResult":222,"../util/tryCatch":224}],137:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../Subject":53,"../util/errorObject":216,"../util/subscribeToResult":238,"../util/tryCatch":240}],153:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13659,7 +20475,7 @@ var RetrySubscriber = (function (_super) {
     return RetrySubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],138:[function(require,module,exports){
+},{"../Subscriber":55}],154:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13748,7 +20564,7 @@ var RetryWhenSubscriber = (function (_super) {
     return RetryWhenSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../Subject":37,"../util/errorObject":200,"../util/subscribeToResult":222,"../util/tryCatch":224}],139:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../Subject":53,"../util/errorObject":216,"../util/subscribeToResult":238,"../util/tryCatch":240}],155:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13808,7 +20624,7 @@ var SampleSubscriber = (function (_super) {
     return SampleSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../util/subscribeToResult":222}],140:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/subscribeToResult":238}],156:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13869,7 +20685,7 @@ function dispatchNotification(state) {
     this.schedule(state, period);
 }
 
-},{"../Subscriber":39,"../scheduler/async":188}],141:[function(require,module,exports){
+},{"../Subscriber":55,"../scheduler/async":204}],157:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -13953,7 +20769,7 @@ var ScanSubscriber = (function (_super) {
     return ScanSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],142:[function(require,module,exports){
+},{"../Subscriber":55}],158:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14083,7 +20899,7 @@ var SequenceEqualCompareToSubscriber = (function (_super) {
     return SequenceEqualCompareToSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39,"../util/errorObject":200,"../util/tryCatch":224}],143:[function(require,module,exports){
+},{"../Subscriber":55,"../util/errorObject":216,"../util/tryCatch":240}],159:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var multicast_1 = require("./multicast");
@@ -14097,7 +20913,7 @@ function share() {
 }
 exports.share = share;
 
-},{"../Subject":37,"./multicast":122,"./refCount":134}],144:[function(require,module,exports){
+},{"../Subject":53,"./multicast":138,"./refCount":150}],160:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var ReplaySubject_1 = require("../ReplaySubject");
@@ -14141,7 +20957,7 @@ function shareReplayOperator(bufferSize, windowTime, scheduler) {
     };
 }
 
-},{"../ReplaySubject":35}],145:[function(require,module,exports){
+},{"../ReplaySubject":51}],161:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14224,7 +21040,7 @@ var SingleSubscriber = (function (_super) {
     return SingleSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39,"../util/EmptyError":194}],146:[function(require,module,exports){
+},{"../Subscriber":55,"../util/EmptyError":210}],162:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14270,7 +21086,7 @@ var SkipSubscriber = (function (_super) {
     return SkipSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],147:[function(require,module,exports){
+},{"../Subscriber":55}],163:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14335,7 +21151,7 @@ var SkipLastSubscriber = (function (_super) {
     return SkipLastSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39,"../util/ArgumentOutOfRangeError":193}],148:[function(require,module,exports){
+},{"../Subscriber":55,"../util/ArgumentOutOfRangeError":209}],164:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14394,7 +21210,7 @@ var SkipUntilSubscriber = (function (_super) {
     return SkipUntilSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../InnerSubscriber":30,"../OuterSubscriber":34,"../util/subscribeToResult":222}],149:[function(require,module,exports){
+},{"../InnerSubscriber":46,"../OuterSubscriber":50,"../util/subscribeToResult":238}],165:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14454,7 +21270,7 @@ var SkipWhileSubscriber = (function (_super) {
     return SkipWhileSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],150:[function(require,module,exports){
+},{"../Subscriber":55}],166:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var fromArray_1 = require("../observable/fromArray");
@@ -14489,7 +21305,7 @@ function startWith() {
 }
 exports.startWith = startWith;
 
-},{"../observable/concat":47,"../observable/empty":49,"../observable/fromArray":52,"../observable/scalar":68,"../util/isScheduler":213}],151:[function(require,module,exports){
+},{"../observable/concat":63,"../observable/empty":65,"../observable/fromArray":68,"../observable/scalar":84,"../util/isScheduler":229}],167:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var SubscribeOnObservable_1 = require("../observable/SubscribeOnObservable");
@@ -14511,7 +21327,7 @@ var SubscribeOnOperator = (function () {
     return SubscribeOnOperator;
 }());
 
-},{"../observable/SubscribeOnObservable":43}],152:[function(require,module,exports){
+},{"../observable/SubscribeOnObservable":59}],168:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var switchMap_1 = require("./switchMap");
@@ -14521,7 +21337,7 @@ function switchAll() {
 }
 exports.switchAll = switchAll;
 
-},{"../util/identity":202,"./switchMap":153}],153:[function(require,module,exports){
+},{"../util/identity":218,"./switchMap":169}],169:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14612,7 +21428,7 @@ var SwitchMapSubscriber = (function (_super) {
     return SwitchMapSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../InnerSubscriber":30,"../OuterSubscriber":34,"../observable/from":51,"../util/subscribeToResult":222,"./map":112}],154:[function(require,module,exports){
+},{"../InnerSubscriber":46,"../OuterSubscriber":50,"../observable/from":67,"../util/subscribeToResult":238,"./map":128}],170:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var switchMap_1 = require("./switchMap");
@@ -14621,7 +21437,7 @@ function switchMapTo(innerObservable, resultSelector) {
 }
 exports.switchMapTo = switchMapTo;
 
-},{"./switchMap":153}],155:[function(require,module,exports){
+},{"./switchMap":169}],171:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14685,7 +21501,7 @@ var TakeSubscriber = (function (_super) {
     return TakeSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39,"../observable/empty":49,"../util/ArgumentOutOfRangeError":193}],156:[function(require,module,exports){
+},{"../Subscriber":55,"../observable/empty":65,"../util/ArgumentOutOfRangeError":209}],172:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14764,7 +21580,7 @@ var TakeLastSubscriber = (function (_super) {
     return TakeLastSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39,"../observable/empty":49,"../util/ArgumentOutOfRangeError":193}],157:[function(require,module,exports){
+},{"../Subscriber":55,"../observable/empty":65,"../util/ArgumentOutOfRangeError":209}],173:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14817,7 +21633,7 @@ var TakeUntilSubscriber = (function (_super) {
     return TakeUntilSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../util/subscribeToResult":222}],158:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/subscribeToResult":238}],174:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14879,7 +21695,7 @@ var TakeWhileSubscriber = (function (_super) {
     return TakeWhileSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39}],159:[function(require,module,exports){
+},{"../Subscriber":55}],175:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -14969,7 +21785,7 @@ var TapSubscriber = (function (_super) {
     return TapSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subscriber":39,"../util/isFunction":206,"../util/noop":214}],160:[function(require,module,exports){
+},{"../Subscriber":55,"../util/isFunction":222,"../util/noop":230}],176:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -15073,7 +21889,7 @@ var ThrottleSubscriber = (function (_super) {
     return ThrottleSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../util/subscribeToResult":222}],161:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/subscribeToResult":238}],177:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -15165,7 +21981,7 @@ function dispatchNext(arg) {
     subscriber.clearThrottle();
 }
 
-},{"../Subscriber":39,"../scheduler/async":188,"./throttle":160}],162:[function(require,module,exports){
+},{"../Subscriber":55,"../scheduler/async":204,"./throttle":176}],178:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var tap_1 = require("./tap");
@@ -15186,7 +22002,7 @@ function defaultErrorFactory() {
     return new EmptyError_1.EmptyError();
 }
 
-},{"../util/EmptyError":194,"./tap":159}],163:[function(require,module,exports){
+},{"../util/EmptyError":210,"./tap":175}],179:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var async_1 = require("../scheduler/async");
@@ -15215,7 +22031,7 @@ var TimeInterval = (function () {
 }());
 exports.TimeInterval = TimeInterval;
 
-},{"../observable/defer":48,"../scheduler/async":188,"./map":112,"./scan":141}],164:[function(require,module,exports){
+},{"../observable/defer":64,"../scheduler/async":204,"./map":128,"./scan":157}],180:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var async_1 = require("../scheduler/async");
@@ -15228,7 +22044,7 @@ function timeout(due, scheduler) {
 }
 exports.timeout = timeout;
 
-},{"../observable/throwError":69,"../scheduler/async":188,"../util/TimeoutError":197,"./timeoutWith":165}],165:[function(require,module,exports){
+},{"../observable/throwError":85,"../scheduler/async":204,"../util/TimeoutError":213,"./timeoutWith":181}],181:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -15309,7 +22125,7 @@ var TimeoutWithSubscriber = (function (_super) {
     return TimeoutWithSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../scheduler/async":188,"../util/isDate":205,"../util/subscribeToResult":222}],166:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../scheduler/async":204,"../util/isDate":221,"../util/subscribeToResult":238}],182:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var async_1 = require("../scheduler/async");
@@ -15328,7 +22144,7 @@ var Timestamp = (function () {
 }());
 exports.Timestamp = Timestamp;
 
-},{"../scheduler/async":188,"./map":112}],167:[function(require,module,exports){
+},{"../scheduler/async":204,"./map":128}],183:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var reduce_1 = require("./reduce");
@@ -15344,7 +22160,7 @@ function toArray() {
 }
 exports.toArray = toArray;
 
-},{"./reduce":133}],168:[function(require,module,exports){
+},{"./reduce":149}],184:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -15426,7 +22242,7 @@ var WindowSubscriber = (function (_super) {
     return WindowSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../Subject":37,"../util/subscribeToResult":222}],169:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../Subject":53,"../util/subscribeToResult":238}],185:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -15517,7 +22333,7 @@ var WindowCountSubscriber = (function (_super) {
     return WindowCountSubscriber;
 }(Subscriber_1.Subscriber));
 
-},{"../Subject":37,"../Subscriber":39}],170:[function(require,module,exports){
+},{"../Subject":53,"../Subscriber":55}],186:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -15687,7 +22503,7 @@ function dispatchWindowClose(state) {
     subscriber.closeWindow(window);
 }
 
-},{"../Subject":37,"../Subscriber":39,"../scheduler/async":188,"../util/isNumeric":209,"../util/isScheduler":213}],171:[function(require,module,exports){
+},{"../Subject":53,"../Subscriber":55,"../scheduler/async":204,"../util/isNumeric":225,"../util/isScheduler":229}],187:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -15832,7 +22648,7 @@ var WindowToggleSubscriber = (function (_super) {
     return WindowToggleSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../Subject":37,"../Subscription":40,"../util/errorObject":200,"../util/subscribeToResult":222,"../util/tryCatch":224}],172:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../Subject":53,"../Subscription":56,"../util/errorObject":216,"../util/subscribeToResult":238,"../util/tryCatch":240}],188:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -15929,7 +22745,7 @@ var WindowSubscriber = (function (_super) {
     return WindowSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../Subject":37,"../util/errorObject":200,"../util/subscribeToResult":222,"../util/tryCatch":224}],173:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../Subject":53,"../util/errorObject":216,"../util/subscribeToResult":238,"../util/tryCatch":240}],189:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16027,7 +22843,7 @@ var WithLatestFromSubscriber = (function (_super) {
     return WithLatestFromSubscriber;
 }(OuterSubscriber_1.OuterSubscriber));
 
-},{"../OuterSubscriber":34,"../util/subscribeToResult":222}],174:[function(require,module,exports){
+},{"../OuterSubscriber":50,"../util/subscribeToResult":238}],190:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var zip_1 = require("../observable/zip");
@@ -16042,7 +22858,7 @@ function zip() {
 }
 exports.zip = zip;
 
-},{"../observable/zip":72}],175:[function(require,module,exports){
+},{"../observable/zip":88}],191:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var zip_1 = require("../observable/zip");
@@ -16051,7 +22867,7 @@ function zipAll(project) {
 }
 exports.zipAll = zipAll;
 
-},{"../observable/zip":72}],176:[function(require,module,exports){
+},{"../observable/zip":88}],192:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16081,7 +22897,7 @@ var Action = (function (_super) {
 }(Subscription_1.Subscription));
 exports.Action = Action;
 
-},{"../Subscription":40}],177:[function(require,module,exports){
+},{"../Subscription":56}],193:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16129,7 +22945,7 @@ var AnimationFrameAction = (function (_super) {
 }(AsyncAction_1.AsyncAction));
 exports.AnimationFrameAction = AnimationFrameAction;
 
-},{"./AsyncAction":181}],178:[function(require,module,exports){
+},{"./AsyncAction":197}],194:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16176,7 +22992,7 @@ var AnimationFrameScheduler = (function (_super) {
 }(AsyncScheduler_1.AsyncScheduler));
 exports.AnimationFrameScheduler = AnimationFrameScheduler;
 
-},{"./AsyncScheduler":182}],179:[function(require,module,exports){
+},{"./AsyncScheduler":198}],195:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16225,7 +23041,7 @@ var AsapAction = (function (_super) {
 }(AsyncAction_1.AsyncAction));
 exports.AsapAction = AsapAction;
 
-},{"../util/Immediate":195,"./AsyncAction":181}],180:[function(require,module,exports){
+},{"../util/Immediate":211,"./AsyncAction":197}],196:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16272,7 +23088,7 @@ var AsapScheduler = (function (_super) {
 }(AsyncScheduler_1.AsyncScheduler));
 exports.AsapScheduler = AsapScheduler;
 
-},{"./AsyncScheduler":182}],181:[function(require,module,exports){
+},{"./AsyncScheduler":198}],197:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16374,7 +23190,7 @@ var AsyncAction = (function (_super) {
 }(Action_1.Action));
 exports.AsyncAction = AsyncAction;
 
-},{"./Action":176}],182:[function(require,module,exports){
+},{"./Action":192}],198:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16442,7 +23258,7 @@ var AsyncScheduler = (function (_super) {
 }(Scheduler_1.Scheduler));
 exports.AsyncScheduler = AsyncScheduler;
 
-},{"../Scheduler":36}],183:[function(require,module,exports){
+},{"../Scheduler":52}],199:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16493,7 +23309,7 @@ var QueueAction = (function (_super) {
 }(AsyncAction_1.AsyncAction));
 exports.QueueAction = QueueAction;
 
-},{"./AsyncAction":181}],184:[function(require,module,exports){
+},{"./AsyncAction":197}],200:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16519,7 +23335,7 @@ var QueueScheduler = (function (_super) {
 }(AsyncScheduler_1.AsyncScheduler));
 exports.QueueScheduler = QueueScheduler;
 
-},{"./AsyncScheduler":182}],185:[function(require,module,exports){
+},{"./AsyncScheduler":198}],201:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -16629,35 +23445,35 @@ var VirtualAction = (function (_super) {
 }(AsyncAction_1.AsyncAction));
 exports.VirtualAction = VirtualAction;
 
-},{"./AsyncAction":181,"./AsyncScheduler":182}],186:[function(require,module,exports){
+},{"./AsyncAction":197,"./AsyncScheduler":198}],202:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var AnimationFrameAction_1 = require("./AnimationFrameAction");
 var AnimationFrameScheduler_1 = require("./AnimationFrameScheduler");
 exports.animationFrame = new AnimationFrameScheduler_1.AnimationFrameScheduler(AnimationFrameAction_1.AnimationFrameAction);
 
-},{"./AnimationFrameAction":177,"./AnimationFrameScheduler":178}],187:[function(require,module,exports){
+},{"./AnimationFrameAction":193,"./AnimationFrameScheduler":194}],203:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var AsapAction_1 = require("./AsapAction");
 var AsapScheduler_1 = require("./AsapScheduler");
 exports.asap = new AsapScheduler_1.AsapScheduler(AsapAction_1.AsapAction);
 
-},{"./AsapAction":179,"./AsapScheduler":180}],188:[function(require,module,exports){
+},{"./AsapAction":195,"./AsapScheduler":196}],204:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var AsyncAction_1 = require("./AsyncAction");
 var AsyncScheduler_1 = require("./AsyncScheduler");
 exports.async = new AsyncScheduler_1.AsyncScheduler(AsyncAction_1.AsyncAction);
 
-},{"./AsyncAction":181,"./AsyncScheduler":182}],189:[function(require,module,exports){
+},{"./AsyncAction":197,"./AsyncScheduler":198}],205:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var QueueAction_1 = require("./QueueAction");
 var QueueScheduler_1 = require("./QueueScheduler");
 exports.queue = new QueueScheduler_1.QueueScheduler(QueueAction_1.QueueAction);
 
-},{"./QueueAction":183,"./QueueScheduler":184}],190:[function(require,module,exports){
+},{"./QueueAction":199,"./QueueScheduler":200}],206:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function getSymbolIterator() {
@@ -16670,12 +23486,12 @@ exports.getSymbolIterator = getSymbolIterator;
 exports.iterator = getSymbolIterator();
 exports.$$iterator = exports.iterator;
 
-},{}],191:[function(require,module,exports){
+},{}],207:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.observable = typeof Symbol === 'function' && Symbol.observable || '@@observable';
 
-},{}],192:[function(require,module,exports){
+},{}],208:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.rxSubscriber = typeof Symbol === 'function'
@@ -16683,7 +23499,7 @@ exports.rxSubscriber = typeof Symbol === 'function'
     : '@@rxSubscriber_' + Math.random();
 exports.$$rxSubscriber = exports.rxSubscriber;
 
-},{}],193:[function(require,module,exports){
+},{}],209:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function ArgumentOutOfRangeErrorImpl() {
@@ -16695,7 +23511,7 @@ function ArgumentOutOfRangeErrorImpl() {
 ArgumentOutOfRangeErrorImpl.prototype = Object.create(Error.prototype);
 exports.ArgumentOutOfRangeError = ArgumentOutOfRangeErrorImpl;
 
-},{}],194:[function(require,module,exports){
+},{}],210:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function EmptyErrorImpl() {
@@ -16707,7 +23523,7 @@ function EmptyErrorImpl() {
 EmptyErrorImpl.prototype = Object.create(Error.prototype);
 exports.EmptyError = EmptyErrorImpl;
 
-},{}],195:[function(require,module,exports){
+},{}],211:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var nextHandle = 1;
@@ -16730,7 +23546,7 @@ exports.Immediate = {
     },
 };
 
-},{}],196:[function(require,module,exports){
+},{}],212:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function ObjectUnsubscribedErrorImpl() {
@@ -16742,7 +23558,7 @@ function ObjectUnsubscribedErrorImpl() {
 ObjectUnsubscribedErrorImpl.prototype = Object.create(Error.prototype);
 exports.ObjectUnsubscribedError = ObjectUnsubscribedErrorImpl;
 
-},{}],197:[function(require,module,exports){
+},{}],213:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function TimeoutErrorImpl() {
@@ -16754,7 +23570,7 @@ function TimeoutErrorImpl() {
 TimeoutErrorImpl.prototype = Object.create(Error.prototype);
 exports.TimeoutError = TimeoutErrorImpl;
 
-},{}],198:[function(require,module,exports){
+},{}],214:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function UnsubscriptionErrorImpl(errors) {
@@ -16768,7 +23584,7 @@ function UnsubscriptionErrorImpl(errors) {
 UnsubscriptionErrorImpl.prototype = Object.create(Error.prototype);
 exports.UnsubscriptionError = UnsubscriptionErrorImpl;
 
-},{}],199:[function(require,module,exports){
+},{}],215:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Subscriber_1 = require("../Subscriber");
@@ -16789,12 +23605,12 @@ function canReportError(observer) {
 }
 exports.canReportError = canReportError;
 
-},{"../Subscriber":39}],200:[function(require,module,exports){
+},{"../Subscriber":55}],216:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.errorObject = { e: {} };
 
-},{}],201:[function(require,module,exports){
+},{}],217:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function hostReportError(err) {
@@ -16802,7 +23618,7 @@ function hostReportError(err) {
 }
 exports.hostReportError = hostReportError;
 
-},{}],202:[function(require,module,exports){
+},{}],218:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function identity(x) {
@@ -16810,17 +23626,17 @@ function identity(x) {
 }
 exports.identity = identity;
 
-},{}],203:[function(require,module,exports){
+},{}],219:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.isArray = Array.isArray || (function (x) { return x && typeof x.length === 'number'; });
 
-},{}],204:[function(require,module,exports){
+},{}],220:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.isArrayLike = (function (x) { return x && typeof x.length === 'number' && typeof x !== 'function'; });
 
-},{}],205:[function(require,module,exports){
+},{}],221:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function isDate(value) {
@@ -16828,7 +23644,7 @@ function isDate(value) {
 }
 exports.isDate = isDate;
 
-},{}],206:[function(require,module,exports){
+},{}],222:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function isFunction(x) {
@@ -16836,7 +23652,7 @@ function isFunction(x) {
 }
 exports.isFunction = isFunction;
 
-},{}],207:[function(require,module,exports){
+},{}],223:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var observable_1 = require("../symbol/observable");
@@ -16845,7 +23661,7 @@ function isInteropObservable(input) {
 }
 exports.isInteropObservable = isInteropObservable;
 
-},{"../symbol/observable":191}],208:[function(require,module,exports){
+},{"../symbol/observable":207}],224:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var iterator_1 = require("../symbol/iterator");
@@ -16854,7 +23670,7 @@ function isIterable(input) {
 }
 exports.isIterable = isIterable;
 
-},{"../symbol/iterator":190}],209:[function(require,module,exports){
+},{"../symbol/iterator":206}],225:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var isArray_1 = require("./isArray");
@@ -16863,7 +23679,7 @@ function isNumeric(val) {
 }
 exports.isNumeric = isNumeric;
 
-},{"./isArray":203}],210:[function(require,module,exports){
+},{"./isArray":219}],226:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function isObject(x) {
@@ -16871,7 +23687,7 @@ function isObject(x) {
 }
 exports.isObject = isObject;
 
-},{}],211:[function(require,module,exports){
+},{}],227:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -16880,7 +23696,7 @@ function isObservable(obj) {
 }
 exports.isObservable = isObservable;
 
-},{"../Observable":32}],212:[function(require,module,exports){
+},{"../Observable":48}],228:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function isPromise(value) {
@@ -16888,7 +23704,7 @@ function isPromise(value) {
 }
 exports.isPromise = isPromise;
 
-},{}],213:[function(require,module,exports){
+},{}],229:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function isScheduler(value) {
@@ -16896,13 +23712,13 @@ function isScheduler(value) {
 }
 exports.isScheduler = isScheduler;
 
-},{}],214:[function(require,module,exports){
+},{}],230:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function noop() { }
 exports.noop = noop;
 
-},{}],215:[function(require,module,exports){
+},{}],231:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function not(pred, thisArg) {
@@ -16915,7 +23731,7 @@ function not(pred, thisArg) {
 }
 exports.not = not;
 
-},{}],216:[function(require,module,exports){
+},{}],232:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var noop_1 = require("./noop");
@@ -16940,7 +23756,7 @@ function pipeFromArray(fns) {
 }
 exports.pipeFromArray = pipeFromArray;
 
-},{"./noop":214}],217:[function(require,module,exports){
+},{"./noop":230}],233:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Observable_1 = require("../Observable");
@@ -16986,7 +23802,7 @@ exports.subscribeTo = function (result) {
     }
 };
 
-},{"../Observable":32,"../symbol/iterator":190,"../symbol/observable":191,"./isArrayLike":204,"./isObject":210,"./isPromise":212,"./subscribeToArray":218,"./subscribeToIterable":219,"./subscribeToObservable":220,"./subscribeToPromise":221}],218:[function(require,module,exports){
+},{"../Observable":48,"../symbol/iterator":206,"../symbol/observable":207,"./isArrayLike":220,"./isObject":226,"./isPromise":228,"./subscribeToArray":234,"./subscribeToIterable":235,"./subscribeToObservable":236,"./subscribeToPromise":237}],234:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.subscribeToArray = function (array) { return function (subscriber) {
@@ -16998,7 +23814,7 @@ exports.subscribeToArray = function (array) { return function (subscriber) {
     }
 }; };
 
-},{}],219:[function(require,module,exports){
+},{}],235:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var iterator_1 = require("../symbol/iterator");
@@ -17025,7 +23841,7 @@ exports.subscribeToIterable = function (iterable) { return function (subscriber)
     return subscriber;
 }; };
 
-},{"../symbol/iterator":190}],220:[function(require,module,exports){
+},{"../symbol/iterator":206}],236:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var observable_1 = require("../symbol/observable");
@@ -17039,7 +23855,7 @@ exports.subscribeToObservable = function (obj) { return function (subscriber) {
     }
 }; };
 
-},{"../symbol/observable":191}],221:[function(require,module,exports){
+},{"../symbol/observable":207}],237:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var hostReportError_1 = require("./hostReportError");
@@ -17054,7 +23870,7 @@ exports.subscribeToPromise = function (promise) { return function (subscriber) {
     return subscriber;
 }; };
 
-},{"./hostReportError":201}],222:[function(require,module,exports){
+},{"./hostReportError":217}],238:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var InnerSubscriber_1 = require("../InnerSubscriber");
@@ -17068,7 +23884,7 @@ function subscribeToResult(outerSubscriber, result, outerValue, outerIndex, dest
 }
 exports.subscribeToResult = subscribeToResult;
 
-},{"../InnerSubscriber":30,"./subscribeTo":217}],223:[function(require,module,exports){
+},{"../InnerSubscriber":46,"./subscribeTo":233}],239:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Subscriber_1 = require("../Subscriber");
@@ -17090,7 +23906,7 @@ function toSubscriber(nextOrObserver, error, complete) {
 }
 exports.toSubscriber = toSubscriber;
 
-},{"../Observer":33,"../Subscriber":39,"../symbol/rxSubscriber":192}],224:[function(require,module,exports){
+},{"../Observer":49,"../Subscriber":55,"../symbol/rxSubscriber":208}],240:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var errorObject_1 = require("./errorObject");
@@ -17110,7 +23926,7 @@ function tryCatch(fn) {
 }
 exports.tryCatch = tryCatch;
 
-},{"./errorObject":200}],225:[function(require,module,exports){
+},{"./errorObject":216}],241:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var audit_1 = require("../internal/operators/audit");
@@ -17322,7 +24138,7 @@ exports.zip = zip_1.zip;
 var zipAll_1 = require("../internal/operators/zipAll");
 exports.zipAll = zipAll_1.zipAll;
 
-},{"../internal/operators/audit":73,"../internal/operators/auditTime":74,"../internal/operators/buffer":75,"../internal/operators/bufferCount":76,"../internal/operators/bufferTime":77,"../internal/operators/bufferToggle":78,"../internal/operators/bufferWhen":79,"../internal/operators/catchError":80,"../internal/operators/combineAll":81,"../internal/operators/combineLatest":82,"../internal/operators/concat":83,"../internal/operators/concatAll":84,"../internal/operators/concatMap":85,"../internal/operators/concatMapTo":86,"../internal/operators/count":87,"../internal/operators/debounce":88,"../internal/operators/debounceTime":89,"../internal/operators/defaultIfEmpty":90,"../internal/operators/delay":91,"../internal/operators/delayWhen":92,"../internal/operators/dematerialize":93,"../internal/operators/distinct":94,"../internal/operators/distinctUntilChanged":95,"../internal/operators/distinctUntilKeyChanged":96,"../internal/operators/elementAt":97,"../internal/operators/endWith":98,"../internal/operators/every":99,"../internal/operators/exhaust":100,"../internal/operators/exhaustMap":101,"../internal/operators/expand":102,"../internal/operators/filter":103,"../internal/operators/finalize":104,"../internal/operators/find":105,"../internal/operators/findIndex":106,"../internal/operators/first":107,"../internal/operators/groupBy":108,"../internal/operators/ignoreElements":109,"../internal/operators/isEmpty":110,"../internal/operators/last":111,"../internal/operators/map":112,"../internal/operators/mapTo":113,"../internal/operators/materialize":114,"../internal/operators/max":115,"../internal/operators/merge":116,"../internal/operators/mergeAll":117,"../internal/operators/mergeMap":118,"../internal/operators/mergeMapTo":119,"../internal/operators/mergeScan":120,"../internal/operators/min":121,"../internal/operators/multicast":122,"../internal/operators/observeOn":123,"../internal/operators/onErrorResumeNext":124,"../internal/operators/pairwise":125,"../internal/operators/partition":126,"../internal/operators/pluck":127,"../internal/operators/publish":128,"../internal/operators/publishBehavior":129,"../internal/operators/publishLast":130,"../internal/operators/publishReplay":131,"../internal/operators/race":132,"../internal/operators/reduce":133,"../internal/operators/refCount":134,"../internal/operators/repeat":135,"../internal/operators/repeatWhen":136,"../internal/operators/retry":137,"../internal/operators/retryWhen":138,"../internal/operators/sample":139,"../internal/operators/sampleTime":140,"../internal/operators/scan":141,"../internal/operators/sequenceEqual":142,"../internal/operators/share":143,"../internal/operators/shareReplay":144,"../internal/operators/single":145,"../internal/operators/skip":146,"../internal/operators/skipLast":147,"../internal/operators/skipUntil":148,"../internal/operators/skipWhile":149,"../internal/operators/startWith":150,"../internal/operators/subscribeOn":151,"../internal/operators/switchAll":152,"../internal/operators/switchMap":153,"../internal/operators/switchMapTo":154,"../internal/operators/take":155,"../internal/operators/takeLast":156,"../internal/operators/takeUntil":157,"../internal/operators/takeWhile":158,"../internal/operators/tap":159,"../internal/operators/throttle":160,"../internal/operators/throttleTime":161,"../internal/operators/throwIfEmpty":162,"../internal/operators/timeInterval":163,"../internal/operators/timeout":164,"../internal/operators/timeoutWith":165,"../internal/operators/timestamp":166,"../internal/operators/toArray":167,"../internal/operators/window":168,"../internal/operators/windowCount":169,"../internal/operators/windowTime":170,"../internal/operators/windowToggle":171,"../internal/operators/windowWhen":172,"../internal/operators/withLatestFrom":173,"../internal/operators/zip":174,"../internal/operators/zipAll":175}],226:[function(require,module,exports){
+},{"../internal/operators/audit":89,"../internal/operators/auditTime":90,"../internal/operators/buffer":91,"../internal/operators/bufferCount":92,"../internal/operators/bufferTime":93,"../internal/operators/bufferToggle":94,"../internal/operators/bufferWhen":95,"../internal/operators/catchError":96,"../internal/operators/combineAll":97,"../internal/operators/combineLatest":98,"../internal/operators/concat":99,"../internal/operators/concatAll":100,"../internal/operators/concatMap":101,"../internal/operators/concatMapTo":102,"../internal/operators/count":103,"../internal/operators/debounce":104,"../internal/operators/debounceTime":105,"../internal/operators/defaultIfEmpty":106,"../internal/operators/delay":107,"../internal/operators/delayWhen":108,"../internal/operators/dematerialize":109,"../internal/operators/distinct":110,"../internal/operators/distinctUntilChanged":111,"../internal/operators/distinctUntilKeyChanged":112,"../internal/operators/elementAt":113,"../internal/operators/endWith":114,"../internal/operators/every":115,"../internal/operators/exhaust":116,"../internal/operators/exhaustMap":117,"../internal/operators/expand":118,"../internal/operators/filter":119,"../internal/operators/finalize":120,"../internal/operators/find":121,"../internal/operators/findIndex":122,"../internal/operators/first":123,"../internal/operators/groupBy":124,"../internal/operators/ignoreElements":125,"../internal/operators/isEmpty":126,"../internal/operators/last":127,"../internal/operators/map":128,"../internal/operators/mapTo":129,"../internal/operators/materialize":130,"../internal/operators/max":131,"../internal/operators/merge":132,"../internal/operators/mergeAll":133,"../internal/operators/mergeMap":134,"../internal/operators/mergeMapTo":135,"../internal/operators/mergeScan":136,"../internal/operators/min":137,"../internal/operators/multicast":138,"../internal/operators/observeOn":139,"../internal/operators/onErrorResumeNext":140,"../internal/operators/pairwise":141,"../internal/operators/partition":142,"../internal/operators/pluck":143,"../internal/operators/publish":144,"../internal/operators/publishBehavior":145,"../internal/operators/publishLast":146,"../internal/operators/publishReplay":147,"../internal/operators/race":148,"../internal/operators/reduce":149,"../internal/operators/refCount":150,"../internal/operators/repeat":151,"../internal/operators/repeatWhen":152,"../internal/operators/retry":153,"../internal/operators/retryWhen":154,"../internal/operators/sample":155,"../internal/operators/sampleTime":156,"../internal/operators/scan":157,"../internal/operators/sequenceEqual":158,"../internal/operators/share":159,"../internal/operators/shareReplay":160,"../internal/operators/single":161,"../internal/operators/skip":162,"../internal/operators/skipLast":163,"../internal/operators/skipUntil":164,"../internal/operators/skipWhile":165,"../internal/operators/startWith":166,"../internal/operators/subscribeOn":167,"../internal/operators/switchAll":168,"../internal/operators/switchMap":169,"../internal/operators/switchMapTo":170,"../internal/operators/take":171,"../internal/operators/takeLast":172,"../internal/operators/takeUntil":173,"../internal/operators/takeWhile":174,"../internal/operators/tap":175,"../internal/operators/throttle":176,"../internal/operators/throttleTime":177,"../internal/operators/throwIfEmpty":178,"../internal/operators/timeInterval":179,"../internal/operators/timeout":180,"../internal/operators/timeoutWith":181,"../internal/operators/timestamp":182,"../internal/operators/toArray":183,"../internal/operators/window":184,"../internal/operators/windowCount":185,"../internal/operators/windowTime":186,"../internal/operators/windowToggle":187,"../internal/operators/windowWhen":188,"../internal/operators/withLatestFrom":189,"../internal/operators/zip":190,"../internal/operators/zipAll":191}],242:[function(require,module,exports){
 // threejs.org/license
 (function(l,ya){"object"===typeof exports&&"undefined"!==typeof module?ya(exports):"function"===typeof define&&define.amd?define(["exports"],ya):ya(l.THREE={})})(this,function(l){function ya(){}function z(a,b){this.x=a||0;this.y=b||0}function I(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];0<arguments.length&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}function fa(a,b,c,d){this._x=a||0;this._y=b||0;this._z=c||0;this._w=void 0!==d?d:1}function p(a,
 b,c){this.x=a||0;this.y=b||0;this.z=c||0}function ra(){this.elements=[1,0,0,0,1,0,0,0,1];0<arguments.length&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}function T(a,b,c,d,e,f,g,h,k,m){Object.defineProperty(this,"id",{value:Ef++});this.uuid=H.generateUUID();this.name="";this.image=void 0!==a?a:T.DEFAULT_IMAGE;this.mipmaps=[];this.mapping=void 0!==b?b:T.DEFAULT_MAPPING;this.wrapS=void 0!==c?c:1001;this.wrapT=void 0!==d?d:1001;this.magFilter=void 0!==
@@ -18273,7 +25089,7 @@ return a.center()}};l.Projector=function(){console.error("THREE.Projector has be
 function(){console.error("THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js");this.domElement=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");this.clear=function(){};this.render=function(){};this.setClearColor=function(){};this.setSize=function(){}};l.SceneUtils={createMultiMaterialObject:function(){console.error("THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js")},detach:function(){console.error("THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js")},
 attach:function(){console.error("THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js")}};l.LensFlare=function(){console.error("THREE.LensFlare has been moved to /examples/js/objects/Lensflare.js")};Object.defineProperty(l,"__esModule",{value:!0})});
 
-},{}],227:[function(require,module,exports){
+},{}],243:[function(require,module,exports){
 'use strict';
 
 module.exports = TinyQueue;
@@ -18360,22 +25176,22 @@ TinyQueue.prototype = {
     }
 };
 
-},{}],228:[function(require,module,exports){
+},{}],244:[function(require,module,exports){
 var createElement = require("./vdom/create-element.js")
 
 module.exports = createElement
 
-},{"./vdom/create-element.js":234}],229:[function(require,module,exports){
+},{"./vdom/create-element.js":250}],245:[function(require,module,exports){
 var diff = require("./vtree/diff.js")
 
 module.exports = diff
 
-},{"./vtree/diff.js":254}],230:[function(require,module,exports){
+},{"./vtree/diff.js":270}],246:[function(require,module,exports){
 var h = require("./virtual-hyperscript/index.js")
 
 module.exports = h
 
-},{"./virtual-hyperscript/index.js":241}],231:[function(require,module,exports){
+},{"./virtual-hyperscript/index.js":257}],247:[function(require,module,exports){
 var diff = require("./diff.js")
 var patch = require("./patch.js")
 var h = require("./h.js")
@@ -18392,12 +25208,12 @@ module.exports = {
     VText: VText
 }
 
-},{"./create-element.js":228,"./diff.js":229,"./h.js":230,"./patch.js":232,"./vnode/vnode.js":250,"./vnode/vtext.js":252}],232:[function(require,module,exports){
+},{"./create-element.js":244,"./diff.js":245,"./h.js":246,"./patch.js":248,"./vnode/vnode.js":266,"./vnode/vtext.js":268}],248:[function(require,module,exports){
 var patch = require("./vdom/patch.js")
 
 module.exports = patch
 
-},{"./vdom/patch.js":237}],233:[function(require,module,exports){
+},{"./vdom/patch.js":253}],249:[function(require,module,exports){
 var isObject = require("is-object")
 var isHook = require("../vnode/is-vhook.js")
 
@@ -18496,7 +25312,7 @@ function getPrototype(value) {
     }
 }
 
-},{"../vnode/is-vhook.js":245,"is-object":20}],234:[function(require,module,exports){
+},{"../vnode/is-vhook.js":261,"is-object":20}],250:[function(require,module,exports){
 var document = require("global/document")
 
 var applyProperties = require("./apply-properties")
@@ -18544,7 +25360,7 @@ function createElement(vnode, opts) {
     return node
 }
 
-},{"../vnode/handle-thunk.js":243,"../vnode/is-vnode.js":246,"../vnode/is-vtext.js":247,"../vnode/is-widget.js":248,"./apply-properties":233,"global/document":16}],235:[function(require,module,exports){
+},{"../vnode/handle-thunk.js":259,"../vnode/is-vnode.js":262,"../vnode/is-vtext.js":263,"../vnode/is-widget.js":264,"./apply-properties":249,"global/document":16}],251:[function(require,module,exports){
 // Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
 // We don't want to read all of the DOM nodes in the tree so we use
 // the in-order tree indexing to eliminate recursion down certain branches.
@@ -18631,7 +25447,7 @@ function ascending(a, b) {
     return a > b ? 1 : -1
 }
 
-},{}],236:[function(require,module,exports){
+},{}],252:[function(require,module,exports){
 var applyProperties = require("./apply-properties")
 
 var isWidget = require("../vnode/is-widget.js")
@@ -18784,7 +25600,7 @@ function replaceRoot(oldRoot, newRoot) {
     return newRoot;
 }
 
-},{"../vnode/is-widget.js":248,"../vnode/vpatch.js":251,"./apply-properties":233,"./update-widget":238}],237:[function(require,module,exports){
+},{"../vnode/is-widget.js":264,"../vnode/vpatch.js":267,"./apply-properties":249,"./update-widget":254}],253:[function(require,module,exports){
 var document = require("global/document")
 var isArray = require("x-is-array")
 
@@ -18866,7 +25682,7 @@ function patchIndices(patches) {
     return indices
 }
 
-},{"./create-element":234,"./dom-index":235,"./patch-op":236,"global/document":16,"x-is-array":273}],238:[function(require,module,exports){
+},{"./create-element":250,"./dom-index":251,"./patch-op":252,"global/document":16,"x-is-array":289}],254:[function(require,module,exports){
 var isWidget = require("../vnode/is-widget.js")
 
 module.exports = updateWidget
@@ -18883,7 +25699,7 @@ function updateWidget(a, b) {
     return false
 }
 
-},{"../vnode/is-widget.js":248}],239:[function(require,module,exports){
+},{"../vnode/is-widget.js":264}],255:[function(require,module,exports){
 'use strict';
 
 var EvStore = require('ev-store');
@@ -18912,7 +25728,7 @@ EvHook.prototype.unhook = function(node, propertyName) {
     es[propName] = undefined;
 };
 
-},{"ev-store":9}],240:[function(require,module,exports){
+},{"ev-store":9}],256:[function(require,module,exports){
 'use strict';
 
 module.exports = SoftSetHook;
@@ -18931,7 +25747,7 @@ SoftSetHook.prototype.hook = function (node, propertyName) {
     }
 };
 
-},{}],241:[function(require,module,exports){
+},{}],257:[function(require,module,exports){
 'use strict';
 
 var isArray = require('x-is-array');
@@ -19070,7 +25886,7 @@ function errorString(obj) {
     }
 }
 
-},{"../vnode/is-thunk":244,"../vnode/is-vhook":245,"../vnode/is-vnode":246,"../vnode/is-vtext":247,"../vnode/is-widget":248,"../vnode/vnode.js":250,"../vnode/vtext.js":252,"./hooks/ev-hook.js":239,"./hooks/soft-set-hook.js":240,"./parse-tag.js":242,"x-is-array":273}],242:[function(require,module,exports){
+},{"../vnode/is-thunk":260,"../vnode/is-vhook":261,"../vnode/is-vnode":262,"../vnode/is-vtext":263,"../vnode/is-widget":264,"../vnode/vnode.js":266,"../vnode/vtext.js":268,"./hooks/ev-hook.js":255,"./hooks/soft-set-hook.js":256,"./parse-tag.js":258,"x-is-array":289}],258:[function(require,module,exports){
 'use strict';
 
 var split = require('browser-split');
@@ -19126,7 +25942,7 @@ function parseTag(tag, props) {
     return props.namespace ? tagName : tagName.toUpperCase();
 }
 
-},{"browser-split":5}],243:[function(require,module,exports){
+},{"browser-split":5}],259:[function(require,module,exports){
 var isVNode = require("./is-vnode")
 var isVText = require("./is-vtext")
 var isWidget = require("./is-widget")
@@ -19168,14 +25984,14 @@ function renderThunk(thunk, previous) {
     return renderedThunk
 }
 
-},{"./is-thunk":244,"./is-vnode":246,"./is-vtext":247,"./is-widget":248}],244:[function(require,module,exports){
+},{"./is-thunk":260,"./is-vnode":262,"./is-vtext":263,"./is-widget":264}],260:[function(require,module,exports){
 module.exports = isThunk
 
 function isThunk(t) {
     return t && t.type === "Thunk"
 }
 
-},{}],245:[function(require,module,exports){
+},{}],261:[function(require,module,exports){
 module.exports = isHook
 
 function isHook(hook) {
@@ -19184,7 +26000,7 @@ function isHook(hook) {
        typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook"))
 }
 
-},{}],246:[function(require,module,exports){
+},{}],262:[function(require,module,exports){
 var version = require("./version")
 
 module.exports = isVirtualNode
@@ -19193,7 +26009,7 @@ function isVirtualNode(x) {
     return x && x.type === "VirtualNode" && x.version === version
 }
 
-},{"./version":249}],247:[function(require,module,exports){
+},{"./version":265}],263:[function(require,module,exports){
 var version = require("./version")
 
 module.exports = isVirtualText
@@ -19202,17 +26018,17 @@ function isVirtualText(x) {
     return x && x.type === "VirtualText" && x.version === version
 }
 
-},{"./version":249}],248:[function(require,module,exports){
+},{"./version":265}],264:[function(require,module,exports){
 module.exports = isWidget
 
 function isWidget(w) {
     return w && w.type === "Widget"
 }
 
-},{}],249:[function(require,module,exports){
+},{}],265:[function(require,module,exports){
 module.exports = "2"
 
-},{}],250:[function(require,module,exports){
+},{}],266:[function(require,module,exports){
 var version = require("./version")
 var isVNode = require("./is-vnode")
 var isWidget = require("./is-widget")
@@ -19286,7 +26102,7 @@ function VirtualNode(tagName, properties, children, key, namespace) {
 VirtualNode.prototype.version = version
 VirtualNode.prototype.type = "VirtualNode"
 
-},{"./is-thunk":244,"./is-vhook":245,"./is-vnode":246,"./is-widget":248,"./version":249}],251:[function(require,module,exports){
+},{"./is-thunk":260,"./is-vhook":261,"./is-vnode":262,"./is-widget":264,"./version":265}],267:[function(require,module,exports){
 var version = require("./version")
 
 VirtualPatch.NONE = 0
@@ -19310,7 +26126,7 @@ function VirtualPatch(type, vNode, patch) {
 VirtualPatch.prototype.version = version
 VirtualPatch.prototype.type = "VirtualPatch"
 
-},{"./version":249}],252:[function(require,module,exports){
+},{"./version":265}],268:[function(require,module,exports){
 var version = require("./version")
 
 module.exports = VirtualText
@@ -19322,7 +26138,7 @@ function VirtualText(text) {
 VirtualText.prototype.version = version
 VirtualText.prototype.type = "VirtualText"
 
-},{"./version":249}],253:[function(require,module,exports){
+},{"./version":265}],269:[function(require,module,exports){
 var isObject = require("is-object")
 var isHook = require("../vnode/is-vhook")
 
@@ -19382,7 +26198,7 @@ function getPrototype(value) {
   }
 }
 
-},{"../vnode/is-vhook":245,"is-object":20}],254:[function(require,module,exports){
+},{"../vnode/is-vhook":261,"is-object":20}],270:[function(require,module,exports){
 var isArray = require("x-is-array")
 
 var VPatch = require("../vnode/vpatch")
@@ -19811,7 +26627,7 @@ function appendPatch(apply, patch) {
     }
 }
 
-},{"../vnode/handle-thunk":243,"../vnode/is-thunk":244,"../vnode/is-vnode":246,"../vnode/is-vtext":247,"../vnode/is-widget":248,"../vnode/vpatch":251,"./diff-props":253,"x-is-array":273}],255:[function(require,module,exports){
+},{"../vnode/handle-thunk":259,"../vnode/is-thunk":260,"../vnode/is-vnode":262,"../vnode/is-vtext":263,"../vnode/is-widget":264,"../vnode/vpatch":267,"./diff-props":269,"x-is-array":289}],271:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -19830,7 +26646,7 @@ define(function (require) {
 });
 })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
 
-},{"./Scheduler":256,"./env":268,"./makePromise":270}],256:[function(require,module,exports){
+},{"./Scheduler":272,"./env":284,"./makePromise":286}],272:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -19912,7 +26728,7 @@ define(function() {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
 
-},{}],257:[function(require,module,exports){
+},{}],273:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -19940,7 +26756,7 @@ define(function() {
        return TimeoutError;
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
-},{}],258:[function(require,module,exports){
+},{}],274:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -19997,7 +26813,7 @@ define(function() {
 
 
 
-},{}],259:[function(require,module,exports){
+},{}],275:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20298,7 +27114,7 @@ define(function(require) {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
 
-},{"../apply":258,"../state":271}],260:[function(require,module,exports){
+},{"../apply":274,"../state":287}],276:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20460,7 +27276,7 @@ define(function() {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
 
-},{}],261:[function(require,module,exports){
+},{}],277:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20489,7 +27305,7 @@ define(function() {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
 
-},{}],262:[function(require,module,exports){
+},{}],278:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20511,7 +27327,7 @@ define(function(require) {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
 
-},{"../state":271}],263:[function(require,module,exports){
+},{"../state":287}],279:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20578,7 +27394,7 @@ define(function() {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
 
-},{}],264:[function(require,module,exports){
+},{}],280:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20604,7 +27420,7 @@ define(function() {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
 
-},{}],265:[function(require,module,exports){
+},{}],281:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20684,7 +27500,7 @@ define(function(require) {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
 
-},{"../TimeoutError":257,"../env":268}],266:[function(require,module,exports){
+},{"../TimeoutError":273,"../env":284}],282:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20772,7 +27588,7 @@ define(function(require) {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
 
-},{"../env":268,"../format":269}],267:[function(require,module,exports){
+},{"../env":284,"../format":285}],283:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20812,7 +27628,7 @@ define(function() {
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
 
 
-},{}],268:[function(require,module,exports){
+},{}],284:[function(require,module,exports){
 (function (process){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
@@ -20890,7 +27706,7 @@ define(function(require) {
 
 }).call(this,require('_process'))
 
-},{"_process":6}],269:[function(require,module,exports){
+},{"_process":6}],285:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -20948,7 +27764,7 @@ define(function() {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
 
-},{}],270:[function(require,module,exports){
+},{}],286:[function(require,module,exports){
 (function (process){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
@@ -21908,7 +28724,7 @@ define(function() {
 
 }).call(this,require('_process'))
 
-},{"_process":6}],271:[function(require,module,exports){
+},{"_process":6}],287:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 /** @author Brian Cavalier */
 /** @author John Hann */
@@ -21945,7 +28761,7 @@ define(function() {
 });
 }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
 
-},{}],272:[function(require,module,exports){
+},{}],288:[function(require,module,exports){
 /** @license MIT License (c) copyright 2010-2014 original author or authors */
 
 /**
@@ -22175,7 +28991,7 @@ define(function (require) {
 });
 })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
 
-},{"./lib/Promise":255,"./lib/TimeoutError":257,"./lib/apply":258,"./lib/decorators/array":259,"./lib/decorators/flow":260,"./lib/decorators/fold":261,"./lib/decorators/inspect":262,"./lib/decorators/iterate":263,"./lib/decorators/progress":264,"./lib/decorators/timed":265,"./lib/decorators/unhandledRejection":266,"./lib/decorators/with":267}],273:[function(require,module,exports){
+},{"./lib/Promise":271,"./lib/TimeoutError":273,"./lib/apply":274,"./lib/decorators/array":275,"./lib/decorators/flow":276,"./lib/decorators/fold":277,"./lib/decorators/inspect":278,"./lib/decorators/iterate":279,"./lib/decorators/progress":280,"./lib/decorators/timed":281,"./lib/decorators/unhandledRejection":282,"./lib/decorators/with":283}],289:[function(require,module,exports){
 var nativeIsArray = Array.isArray
 var toString = Object.prototype.toString
 
@@ -22185,7 +29001,7 @@ function isArray(obj) {
     return toString.call(obj) === "[object Array]"
 }
 
-},{}],274:[function(require,module,exports){
+},{}],290:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var APIv3_1 = require("./api/APIv3");
@@ -22193,7 +29009,7 @@ exports.APIv3 = APIv3_1.APIv3;
 var ModelCreator_1 = require("./api/ModelCreator");
 exports.ModelCreator = ModelCreator_1.ModelCreator;
 
-},{"./api/APIv3":287,"./api/ModelCreator":288}],275:[function(require,module,exports){
+},{"./api/APIv3":303,"./api/ModelCreator":304}],291:[function(require,module,exports){
 "use strict";
 function __export(m) {
     for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
@@ -22211,6 +29027,8 @@ var MeshScene_1 = require("./component/utils/MeshScene");
 exports.MeshScene = MeshScene_1.MeshScene;
 var MouseOperator_1 = require("./component/utils/MouseOperator");
 exports.MouseOperator = MouseOperator_1.MouseOperator;
+var ComponentSize_1 = require("./component/utils/ComponentSize");
+exports.ComponentSize = ComponentSize_1.ComponentSize;
 var AttributionComponent_1 = require("./component/AttributionComponent");
 exports.AttributionComponent = AttributionComponent_1.AttributionComponent;
 var BackgroundComponent_1 = require("./component/BackgroundComponent");
@@ -22313,6 +29131,8 @@ var CreatePointHandler_1 = require("./component/tag/handlers/CreatePointHandler"
 exports.CreatePointHandler = CreatePointHandler_1.CreatePointHandler;
 var CreateVertexHandler_1 = require("./component/tag/handlers/CreateVertexHandler");
 exports.CreateVertexHandler = CreateVertexHandler_1.CreateVertexHandler;
+var CreatePointsHandler_1 = require("./component/tag/handlers/CreatePointsHandler");
+exports.CreatePointsHandler = CreatePointsHandler_1.CreatePointsHandler;
 var CreatePolygonHandler_1 = require("./component/tag/handlers/CreatePolygonHandler");
 exports.CreatePolygonHandler = CreatePolygonHandler_1.CreatePolygonHandler;
 var CreateRectHandler_1 = require("./component/tag/handlers/CreateRectHandler");
@@ -22325,12 +29145,16 @@ var Tag_1 = require("./component/tag/tag/Tag");
 exports.Tag = Tag_1.Tag;
 var OutlineTag_1 = require("./component/tag/tag/OutlineTag");
 exports.OutlineTag = OutlineTag_1.OutlineTag;
+var ExtremePointTag_1 = require("./component/tag/tag/ExtremePointTag");
+exports.ExtremePointTag = ExtremePointTag_1.ExtremePointTag;
 var RenderTag_1 = require("./component/tag/tag/RenderTag");
 exports.RenderTag = RenderTag_1.RenderTag;
+var OutlineRenderTagBase_1 = require("./component/tag/tag/OutlineRenderTagBase");
+exports.OutlineRenderTagBase = OutlineRenderTagBase_1.OutlineRenderTagBase;
 var OutlineRenderTag_1 = require("./component/tag/tag/OutlineRenderTag");
 exports.OutlineRenderTag = OutlineRenderTag_1.OutlineRenderTag;
-var OutlineCreateTag_1 = require("./component/tag/tag/OutlineCreateTag");
-exports.OutlineCreateTag = OutlineCreateTag_1.OutlineCreateTag;
+var ExtremePointRenderTag_1 = require("./component/tag/tag/ExtremePointRenderTag");
+exports.ExtremePointRenderTag = ExtremePointRenderTag_1.ExtremePointRenderTag;
 var SpotTag_1 = require("./component/tag/tag/SpotTag");
 exports.SpotTag = SpotTag_1.SpotTag;
 var SpotRenderTag_1 = require("./component/tag/tag/SpotRenderTag");
@@ -22359,15 +29183,23 @@ var RectGeometry_1 = require("./component/tag/geometry/RectGeometry");
 exports.RectGeometry = RectGeometry_1.RectGeometry;
 var PointGeometry_1 = require("./component/tag/geometry/PointGeometry");
 exports.PointGeometry = PointGeometry_1.PointGeometry;
+var PointsGeometry_1 = require("./component/tag/geometry/PointsGeometry");
+exports.PointsGeometry = PointsGeometry_1.PointsGeometry;
 var PolygonGeometry_1 = require("./component/tag/geometry/PolygonGeometry");
 exports.PolygonGeometry = PolygonGeometry_1.PolygonGeometry;
 var GeometryTagError_1 = require("./component/tag/error/GeometryTagError");
 exports.GeometryTagError = GeometryTagError_1.GeometryTagError;
 var ZoomComponent_1 = require("./component/zoom/ZoomComponent");
 exports.ZoomComponent = ZoomComponent_1.ZoomComponent;
+var CreateTag_1 = require("./component/tag/tag/CreateTag");
+exports.CreateTag = CreateTag_1.CreateTag;
+var OutlineCreateTag_1 = require("./component/tag/tag/OutlineCreateTag");
+exports.OutlineCreateTag = OutlineCreateTag_1.OutlineCreateTag;
+var ExtremePointCreateTag_1 = require("./component/tag/tag/ExtremePointCreateTag");
+exports.ExtremePointCreateTag = ExtremePointCreateTag_1.ExtremePointCreateTag;
 __export(require("./component/interfaces/interfaces"));
 
-},{"./component/AttributionComponent":289,"./component/BackgroundComponent":290,"./component/BearingComponent":291,"./component/CacheComponent":292,"./component/Component":293,"./component/ComponentService":294,"./component/CoverComponent":295,"./component/DebugComponent":296,"./component/ImageComponent":297,"./component/LoadingComponent":298,"./component/NavigationComponent":299,"./component/RouteComponent":300,"./component/StatsComponent":301,"./component/direction/DirectionComponent":302,"./component/direction/DirectionDOMCalculator":303,"./component/direction/DirectionDOMRenderer":304,"./component/imageplane/ImagePlaneComponent":305,"./component/imageplane/ImagePlaneGLRenderer":306,"./component/interfaces/interfaces":309,"./component/keyboard/KeyPlayHandler":310,"./component/keyboard/KeySequenceNavigationHandler":311,"./component/keyboard/KeySpatialNavigationHandler":312,"./component/keyboard/KeyZoomHandler":313,"./component/keyboard/KeyboardComponent":314,"./component/marker/MarkerComponent":316,"./component/marker/MarkerScene":317,"./component/marker/MarkerSet":318,"./component/marker/marker/CircleMarker":319,"./component/marker/marker/Marker":320,"./component/marker/marker/SimpleMarker":321,"./component/mouse/BounceHandler":322,"./component/mouse/DoubleClickZoomHandler":323,"./component/mouse/DragPanHandler":324,"./component/mouse/EarthControlHandler":325,"./component/mouse/ImageBoundary":326,"./component/mouse/MouseComponent":327,"./component/mouse/ScrollZoomHandler":328,"./component/mouse/TouchZoomHandler":329,"./component/popup/PopupComponent":331,"./component/popup/popup/Popup":332,"./component/sequence/SequenceComponent":333,"./component/sequence/SequenceDOMRenderer":334,"./component/sequence/SequenceMode":335,"./component/shaders/Shaders":336,"./component/slider/SliderComponent":337,"./component/slider/SliderDOMRenderer":338,"./component/slider/SliderGLRenderer":339,"./component/spatialdata/SpatialDataCache":340,"./component/spatialdata/SpatialDataComponent":341,"./component/spatialdata/SpatialDataScene":342,"./component/tag/TagComponent":344,"./component/tag/TagCreator":345,"./component/tag/TagDOMRenderer":346,"./component/tag/TagMode":347,"./component/tag/TagOperation":348,"./component/tag/TagScene":349,"./component/tag/TagSet":350,"./component/tag/error/GeometryTagError":351,"./component/tag/geometry/Geometry":352,"./component/tag/geometry/PointGeometry":353,"./component/tag/geometry/PolygonGeometry":354,"./component/tag/geometry/RectGeometry":355,"./component/tag/geometry/VertexGeometry":356,"./component/tag/handlers/CreateHandlerBase":357,"./component/tag/handlers/CreatePointHandler":358,"./component/tag/handlers/CreatePolygonHandler":359,"./component/tag/handlers/CreateRectDragHandler":360,"./component/tag/handlers/CreateRectHandler":361,"./component/tag/handlers/CreateVertexHandler":362,"./component/tag/handlers/EditVertexHandler":363,"./component/tag/handlers/TagHandlerBase":364,"./component/tag/tag/OutlineCreateTag":365,"./component/tag/tag/OutlineRenderTag":366,"./component/tag/tag/OutlineTag":367,"./component/tag/tag/RenderTag":368,"./component/tag/tag/SpotRenderTag":369,"./component/tag/tag/SpotTag":370,"./component/tag/tag/Tag":371,"./component/tag/tag/TagDomain":372,"./component/utils/HandlerBase":373,"./component/utils/MeshFactory":374,"./component/utils/MeshScene":375,"./component/utils/MouseOperator":376,"./component/zoom/ZoomComponent":377}],276:[function(require,module,exports){
+},{"./component/AttributionComponent":305,"./component/BackgroundComponent":306,"./component/BearingComponent":307,"./component/CacheComponent":308,"./component/Component":309,"./component/ComponentService":310,"./component/CoverComponent":311,"./component/DebugComponent":312,"./component/ImageComponent":313,"./component/LoadingComponent":314,"./component/NavigationComponent":315,"./component/RouteComponent":316,"./component/StatsComponent":317,"./component/direction/DirectionComponent":318,"./component/direction/DirectionDOMCalculator":319,"./component/direction/DirectionDOMRenderer":320,"./component/imageplane/ImagePlaneComponent":321,"./component/imageplane/ImagePlaneGLRenderer":322,"./component/interfaces/interfaces":325,"./component/keyboard/KeyPlayHandler":326,"./component/keyboard/KeySequenceNavigationHandler":327,"./component/keyboard/KeySpatialNavigationHandler":328,"./component/keyboard/KeyZoomHandler":329,"./component/keyboard/KeyboardComponent":330,"./component/marker/MarkerComponent":332,"./component/marker/MarkerScene":333,"./component/marker/MarkerSet":334,"./component/marker/marker/CircleMarker":335,"./component/marker/marker/Marker":336,"./component/marker/marker/SimpleMarker":337,"./component/mouse/BounceHandler":338,"./component/mouse/DoubleClickZoomHandler":339,"./component/mouse/DragPanHandler":340,"./component/mouse/EarthControlHandler":341,"./component/mouse/ImageBoundary":342,"./component/mouse/MouseComponent":343,"./component/mouse/ScrollZoomHandler":344,"./component/mouse/TouchZoomHandler":345,"./component/popup/PopupComponent":347,"./component/popup/popup/Popup":348,"./component/sequence/SequenceComponent":349,"./component/sequence/SequenceDOMRenderer":350,"./component/sequence/SequenceMode":351,"./component/shaders/Shaders":352,"./component/slider/SliderComponent":353,"./component/slider/SliderDOMRenderer":354,"./component/slider/SliderGLRenderer":355,"./component/spatialdata/SpatialDataCache":358,"./component/spatialdata/SpatialDataComponent":359,"./component/spatialdata/SpatialDataScene":360,"./component/tag/TagComponent":362,"./component/tag/TagCreator":363,"./component/tag/TagDOMRenderer":364,"./component/tag/TagMode":365,"./component/tag/TagOperation":366,"./component/tag/TagScene":367,"./component/tag/TagSet":368,"./component/tag/error/GeometryTagError":369,"./component/tag/geometry/Geometry":370,"./component/tag/geometry/PointGeometry":371,"./component/tag/geometry/PointsGeometry":372,"./component/tag/geometry/PolygonGeometry":373,"./component/tag/geometry/RectGeometry":374,"./component/tag/geometry/VertexGeometry":375,"./component/tag/handlers/CreateHandlerBase":376,"./component/tag/handlers/CreatePointHandler":377,"./component/tag/handlers/CreatePointsHandler":378,"./component/tag/handlers/CreatePolygonHandler":379,"./component/tag/handlers/CreateRectDragHandler":380,"./component/tag/handlers/CreateRectHandler":381,"./component/tag/handlers/CreateVertexHandler":382,"./component/tag/handlers/EditVertexHandler":383,"./component/tag/handlers/TagHandlerBase":384,"./component/tag/tag/CreateTag":385,"./component/tag/tag/ExtremePointCreateTag":386,"./component/tag/tag/ExtremePointRenderTag":387,"./component/tag/tag/ExtremePointTag":388,"./component/tag/tag/OutlineCreateTag":389,"./component/tag/tag/OutlineRenderTag":390,"./component/tag/tag/OutlineRenderTagBase":391,"./component/tag/tag/OutlineTag":392,"./component/tag/tag/RenderTag":393,"./component/tag/tag/SpotRenderTag":394,"./component/tag/tag/SpotTag":395,"./component/tag/tag/Tag":396,"./component/tag/tag/TagDomain":397,"./component/utils/ComponentSize":398,"./component/utils/HandlerBase":399,"./component/utils/MeshFactory":400,"./component/utils/MeshScene":401,"./component/utils/MouseOperator":402,"./component/zoom/ZoomComponent":403}],292:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var EdgeDirection_1 = require("./graph/edge/EdgeDirection");
@@ -22381,7 +29213,7 @@ exports.EdgeCalculatorCoefficients = EdgeCalculatorCoefficients_1.EdgeCalculator
 var EdgeCalculator_1 = require("./graph/edge/EdgeCalculator");
 exports.EdgeCalculator = EdgeCalculator_1.EdgeCalculator;
 
-},{"./graph/edge/EdgeCalculator":399,"./graph/edge/EdgeCalculatorCoefficients":400,"./graph/edge/EdgeCalculatorDirections":401,"./graph/edge/EdgeCalculatorSettings":402,"./graph/edge/EdgeDirection":403}],277:[function(require,module,exports){
+},{"./graph/edge/EdgeCalculator":425,"./graph/edge/EdgeCalculatorCoefficients":426,"./graph/edge/EdgeCalculatorDirections":427,"./graph/edge/EdgeCalculatorSettings":428,"./graph/edge/EdgeDirection":429}],293:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var AbortMapillaryError_1 = require("./error/AbortMapillaryError");
@@ -22393,7 +29225,7 @@ exports.GraphMapillaryError = GraphMapillaryError_1.GraphMapillaryError;
 var MapillaryError_1 = require("./error/MapillaryError");
 exports.MapillaryError = MapillaryError_1.MapillaryError;
 
-},{"./error/AbortMapillaryError":378,"./error/ArgumentMapillaryError":379,"./error/GraphMapillaryError":380,"./error/MapillaryError":381}],278:[function(require,module,exports){
+},{"./error/AbortMapillaryError":404,"./error/ArgumentMapillaryError":405,"./error/GraphMapillaryError":406,"./error/MapillaryError":407}],294:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Camera_1 = require("./geo/Camera");
@@ -22411,7 +29243,7 @@ exports.Geo = Geo;
 var Lines = require("./geo/Lines");
 exports.Lines = Lines;
 
-},{"./geo/Camera":382,"./geo/Geo":383,"./geo/GeoCoords":384,"./geo/Lines":385,"./geo/Spatial":386,"./geo/Transform":387,"./geo/ViewportCoords":388}],279:[function(require,module,exports){
+},{"./geo/Camera":408,"./geo/Geo":409,"./geo/GeoCoords":410,"./geo/Lines":411,"./geo/Spatial":412,"./geo/Transform":413,"./geo/ViewportCoords":414}],295:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var FilterCreator_1 = require("./graph/FilterCreator");
@@ -22435,7 +29267,7 @@ exports.NodeCache = NodeCache_1.NodeCache;
 var Sequence_1 = require("./graph/Sequence");
 exports.Sequence = Sequence_1.Sequence;
 
-},{"./graph/FilterCreator":389,"./graph/Graph":390,"./graph/GraphCalculator":391,"./graph/GraphMode":392,"./graph/GraphService":393,"./graph/ImageLoadingService":394,"./graph/MeshReader":395,"./graph/Node":396,"./graph/NodeCache":397,"./graph/Sequence":398}],280:[function(require,module,exports){
+},{"./graph/FilterCreator":415,"./graph/Graph":416,"./graph/GraphCalculator":417,"./graph/GraphMode":418,"./graph/GraphService":419,"./graph/ImageLoadingService":420,"./graph/MeshReader":421,"./graph/Node":422,"./graph/NodeCache":423,"./graph/Sequence":424}],296:[function(require,module,exports){
 "use strict";
 /**
  * MapillaryJS is a WebGL JavaScript library for exploring street level imagery
@@ -22460,14 +29292,17 @@ exports.ImageSize = Viewer_1.ImageSize;
 exports.Viewer = Viewer_1.Viewer;
 var Component_1 = require("./Component");
 exports.SliderMode = Component_1.SliderMode;
+exports.ComponentSize = Component_1.ComponentSize;
 var TagComponent = require("./component/tag/Tag");
 exports.TagComponent = TagComponent;
 var MarkerComponent = require("./component/marker/Marker");
 exports.MarkerComponent = MarkerComponent;
 var PopupComponent = require("./component/popup/Popup");
 exports.PopupComponent = PopupComponent;
+var SpatialDataComponent = require("./component/spatialdata/SpatialData");
+exports.SpatialDataComponent = SpatialDataComponent;
 
-},{"./Component":275,"./Edge":276,"./Error":277,"./Render":281,"./State":282,"./Support":283,"./Viewer":286,"./component/marker/Marker":315,"./component/popup/Popup":330,"./component/tag/Tag":343}],281:[function(require,module,exports){
+},{"./Component":291,"./Edge":292,"./Error":293,"./Render":297,"./State":298,"./Support":299,"./Viewer":302,"./component/marker/Marker":331,"./component/popup/Popup":346,"./component/spatialdata/SpatialData":357,"./component/tag/Tag":361}],297:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var DOMRenderer_1 = require("./render/DOMRenderer");
@@ -22483,7 +29318,7 @@ exports.RenderMode = RenderMode_1.RenderMode;
 var RenderService_1 = require("./render/RenderService");
 exports.RenderService = RenderService_1.RenderService;
 
-},{"./render/DOMRenderer":404,"./render/GLRenderStage":405,"./render/GLRenderer":406,"./render/RenderCamera":407,"./render/RenderMode":408,"./render/RenderService":409}],282:[function(require,module,exports){
+},{"./render/DOMRenderer":430,"./render/GLRenderStage":431,"./render/GLRenderer":432,"./render/RenderCamera":433,"./render/RenderMode":434,"./render/RenderService":435}],298:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var FrameGenerator_1 = require("./state/FrameGenerator");
@@ -22511,7 +29346,7 @@ exports.TraversingState = TraversingState_1.TraversingState;
 var WaitingState_1 = require("./state/states/WaitingState");
 exports.WaitingState = WaitingState_1.WaitingState;
 
-},{"./state/FrameGenerator":410,"./state/RotationDelta":411,"./state/State":412,"./state/StateContext":413,"./state/StateService":414,"./state/TransitionMode":415,"./state/states/EarthState":416,"./state/states/InteractiveStateBase":417,"./state/states/InteractiveWaitingState":418,"./state/states/StateBase":419,"./state/states/TraversingState":420,"./state/states/WaitingState":421}],283:[function(require,module,exports){
+},{"./state/FrameGenerator":436,"./state/RotationDelta":437,"./state/State":438,"./state/StateContext":439,"./state/StateService":440,"./state/TransitionMode":441,"./state/states/EarthState":442,"./state/states/InteractiveStateBase":443,"./state/states/InteractiveWaitingState":444,"./state/states/StateBase":445,"./state/states/TraversingState":446,"./state/states/WaitingState":447}],299:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var support = require("./utils/Support");
@@ -22551,7 +29386,7 @@ function isFallbackSupported() {
 }
 exports.isFallbackSupported = isFallbackSupported;
 
-},{"./utils/Support":429}],284:[function(require,module,exports){
+},{"./utils/Support":455}],300:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var ImageTileLoader_1 = require("./tiles/ImageTileLoader");
@@ -22563,7 +29398,7 @@ exports.TextureProvider = TextureProvider_1.TextureProvider;
 var RegionOfInterestCalculator_1 = require("./tiles/RegionOfInterestCalculator");
 exports.RegionOfInterestCalculator = RegionOfInterestCalculator_1.RegionOfInterestCalculator;
 
-},{"./tiles/ImageTileLoader":422,"./tiles/ImageTileStore":423,"./tiles/RegionOfInterestCalculator":424,"./tiles/TextureProvider":425}],285:[function(require,module,exports){
+},{"./tiles/ImageTileLoader":448,"./tiles/ImageTileStore":449,"./tiles/RegionOfInterestCalculator":450,"./tiles/TextureProvider":451}],301:[function(require,module,exports){
 "use strict";
 function __export(m) {
     for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
@@ -22579,7 +29414,7 @@ __export(require("./utils/Support"));
 var Urls_1 = require("./utils/Urls");
 exports.Urls = Urls_1.Urls;
 
-},{"./utils/DOM":426,"./utils/EventEmitter":427,"./utils/Settings":428,"./utils/Support":429,"./utils/Urls":430}],286:[function(require,module,exports){
+},{"./utils/DOM":452,"./utils/EventEmitter":453,"./utils/Settings":454,"./utils/Support":455,"./utils/Urls":456}],302:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Alignment_1 = require("./viewer/Alignment");
@@ -22613,7 +29448,7 @@ exports.TouchService = TouchService_1.TouchService;
 var Viewer_1 = require("./viewer/Viewer");
 exports.Viewer = Viewer_1.Viewer;
 
-},{"./viewer/Alignment":431,"./viewer/CacheService":432,"./viewer/ComponentController":433,"./viewer/Container":434,"./viewer/ImageSize":435,"./viewer/KeyboardService":436,"./viewer/LoadingService":437,"./viewer/MouseService":438,"./viewer/Navigator":439,"./viewer/Observer":440,"./viewer/PlayService":441,"./viewer/Projection":442,"./viewer/SpriteService":443,"./viewer/TouchService":444,"./viewer/Viewer":445}],287:[function(require,module,exports){
+},{"./viewer/Alignment":457,"./viewer/CacheService":458,"./viewer/ComponentController":459,"./viewer/Container":460,"./viewer/ImageSize":461,"./viewer/KeyboardService":462,"./viewer/LoadingService":463,"./viewer/MouseService":464,"./viewer/Navigator":465,"./viewer/Observer":466,"./viewer/PlayService":468,"./viewer/Projection":469,"./viewer/SpriteService":470,"./viewer/TouchService":471,"./viewer/Viewer":472}],303:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
@@ -22665,6 +29500,7 @@ var APIv3 = /** @class */ (function () {
         ];
         this._propertiesSpatial = [
             "atomic_scale",
+            "cluster_key",
             "c_rotation",
             "ca",
             "calt",
@@ -22843,7 +29679,7 @@ var APIv3 = /** @class */ (function () {
 exports.APIv3 = APIv3;
 exports.default = APIv3;
 
-},{"../API":274,"rxjs":27,"rxjs/operators":225}],288:[function(require,module,exports){
+},{"../API":290,"rxjs":43,"rxjs/operators":241}],304:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var falcor = require("falcor");
@@ -22886,7 +29722,7 @@ var ModelCreator = /** @class */ (function () {
 exports.ModelCreator = ModelCreator;
 exports.default = ModelCreator;
 
-},{"../Utils":285,"falcor":15,"falcor-http-datasource":10}],289:[function(require,module,exports){
+},{"../Utils":301,"falcor":15,"falcor-http-datasource":10}],305:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -22953,7 +29789,7 @@ exports.AttributionComponent = AttributionComponent;
 Component_1.ComponentService.register(AttributionComponent);
 exports.default = AttributionComponent;
 
-},{"../Component":275,"../Utils":285,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],290:[function(require,module,exports){
+},{"../Component":291,"../Utils":301,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],306:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -22999,7 +29835,7 @@ exports.BackgroundComponent = BackgroundComponent;
 Component_1.ComponentService.register(BackgroundComponent);
 exports.default = BackgroundComponent;
 
-},{"../Component":275,"virtual-dom":231}],291:[function(require,module,exports){
+},{"../Component":291,"virtual-dom":247}],307:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -23017,15 +29853,38 @@ var __extends = (this && this.__extends) || (function () {
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
 var vd = require("virtual-dom");
+var UnitBezier = require("@mapbox/unitbezier");
+var rxjs_1 = require("rxjs");
 var Component_1 = require("../Component");
 var Geo_1 = require("../Geo");
+var ViewportCoords_1 = require("../geo/ViewportCoords");
+var ComponentSize_1 = require("./utils/ComponentSize");
+/**
+ * @class BearingComponent
+ *
+ * @classdesc Component for indicating bearing and field of view.
+ *
+ * @example
+ * ```
+ * var viewer = new Mapillary.Viewer(
+ *     "<element-id>",
+ *     "<client-id>",
+ *     "<my key>");
+ *
+ * var bearingComponent = viewer.getComponent("bearing");
+ * bearingComponent.configure({ size: Mapillary.ComponentSize.Small });
+ * ```
+ */
 var BearingComponent = /** @class */ (function (_super) {
     __extends(BearingComponent, _super);
     function BearingComponent(name, container, navigator) {
         var _this = _super.call(this, name, container, navigator) || this;
         _this._spatial = new Geo_1.Spatial();
+        _this._viewportCoords = new ViewportCoords_1.default();
         _this._svgNamespace = "http://www.w3.org/2000/svg";
         _this._distinctThreshold = Math.PI / 360;
+        _this._animationSpeed = 0.075;
+        _this._unitBezier = new UnitBezier(0.74, 0.67, 0.38, 0.96);
         return _this;
     }
     BearingComponent.prototype._activate = function () {
@@ -23040,17 +29899,110 @@ var BearingComponent = /** @class */ (function (_super) {
             return Math.abs(a2[0] - a1[0]) < _this._distinctThreshold &&
                 Math.abs(a2[1] - a1[1]) < _this._distinctThreshold;
         }));
-        this._renderSubscription = cameraBearingFov$.pipe(operators_1.map(function (_a) {
-            var bearing = _a[0], fov = _a[1];
-            var background = vd.h("div.BearingIndicatorBackground", {}, []);
-            var backgroundCircle = vd.h("div.BearingIndicatorBackgroundCircle", {}, []);
-            var north = _this._createNorth(bearing);
-            var cameraSector = _this._createCircleSectorCompass(_this._createCircleSector(Math.max(Math.PI / 20, fov), "#FFF"));
+        var nodeFov$ = rxjs_1.combineLatest(this._navigator.stateService.currentState$.pipe(operators_1.distinctUntilChanged(undefined, function (frame) {
+            return frame.state.currentNode.key;
+        })), this._navigator.panService.panNodes$).pipe(operators_1.map(function (_a) {
+            var frame = _a[0], panNodes = _a[1];
+            var node = frame.state.currentNode;
+            var transform = frame.state.currentTransform;
+            if (node.pano) {
+                var panoHFov = 2 * Math.PI * node.gpano.CroppedAreaImageWidthPixels / node.gpano.FullPanoWidthPixels;
+                return [panoHFov / 2, panoHFov / 2];
+            }
+            var currentProjectedPoints = _this._computeProjectedPoints(transform);
+            var hFov = _this._spatial.degToRad(_this._computeHorizontalFov(currentProjectedPoints));
+            var hFovLeft = hFov / 2;
+            var hFovRight = hFov / 2;
+            for (var _i = 0, panNodes_1 = panNodes; _i < panNodes_1.length; _i++) {
+                var _b = panNodes_1[_i], n = _b[0], f = _b[2];
+                var diff = _this._spatial.wrap(n.ca - node.ca, -180, 180);
+                if (diff < 0) {
+                    hFovLeft = _this._spatial.degToRad(Math.abs(diff)) + f / 2;
+                }
+                else {
+                    hFovRight = _this._spatial.degToRad(Math.abs(diff)) + f / 2;
+                }
+            }
+            return [hFovLeft, hFovRight];
+        }), operators_1.distinctUntilChanged(function (_a, _b) {
+            var hFovLeft1 = _a[0], hFovRight1 = _a[1];
+            var hFovLeft2 = _b[0], hFovRight2 = _b[1];
+            return Math.abs(hFovLeft2 - hFovLeft1) < _this._distinctThreshold &&
+                Math.abs(hFovRight2 - hFovRight1) < _this._distinctThreshold;
+        }));
+        var offset$ = rxjs_1.combineLatest(this._navigator.stateService.currentState$.pipe(operators_1.distinctUntilChanged(undefined, function (frame) {
+            return frame.state.currentNode.key;
+        })), this._container.renderService.bearing$).pipe(operators_1.map(function (_a) {
+            var frame = _a[0], bearing = _a[1];
+            var offset = _this._spatial.degToRad(frame.state.currentNode.ca - bearing);
+            return offset;
+        }));
+        var nodeFovOperation$ = new rxjs_1.Subject();
+        var smoothNodeFov$ = nodeFovOperation$.pipe(operators_1.scan(function (state, operation) {
+            return operation(state);
+        }, { alpha: 0, curr: [0, 0, 0], prev: [0, 0, 0] }), operators_1.map(function (state) {
+            var alpha = _this._unitBezier.solve(state.alpha);
+            var curr = state.curr;
+            var prev = state.prev;
+            return [
+                _this._interpolate(prev[0], curr[0], alpha),
+                _this._interpolate(prev[1], curr[1], alpha),
+            ];
+        }));
+        this._fovSubscription = nodeFov$.pipe(operators_1.map(function (nbf) {
+            return function (state) {
+                var a = _this._unitBezier.solve(state.alpha);
+                var c = state.curr;
+                var p = state.prev;
+                var prev = [
+                    _this._interpolate(p[0], c[0], a),
+                    _this._interpolate(p[1], c[1], a),
+                ];
+                var curr = nbf.slice();
+                return {
+                    alpha: 0,
+                    curr: curr,
+                    prev: prev,
+                };
+            };
+        }))
+            .subscribe(nodeFovOperation$);
+        this._fovAnimationSubscription = nodeFov$.pipe(operators_1.switchMap(function () {
+            return _this._container.renderService.renderCameraFrame$.pipe(operators_1.skip(1), operators_1.scan(function (alpha) {
+                return alpha + _this._animationSpeed;
+            }, 0), operators_1.takeWhile(function (alpha) {
+                return alpha <= 1 + _this._animationSpeed;
+            }), operators_1.map(function (alpha) {
+                return Math.min(alpha, 1);
+            }));
+        }), operators_1.map(function (alpha) {
+            return function (nbfState) {
+                return {
+                    alpha: alpha,
+                    curr: nbfState.curr.slice(),
+                    prev: nbfState.prev.slice(),
+                };
+            };
+        }))
+            .subscribe(nodeFovOperation$);
+        var nodeBearingFov$ = rxjs_1.combineLatest(offset$, smoothNodeFov$).pipe(operators_1.map(function (_a) {
+            var offset = _a[0], fov = _a[1];
+            return [offset, fov[0], fov[1]];
+        }));
+        this._renderSubscription = rxjs_1.combineLatest(cameraBearingFov$, nodeBearingFov$, this._configuration$, this._container.renderService.size$).pipe(operators_1.map(function (_a) {
+            var _b = _a[0], cb = _b[0], cf = _b[1], _c = _a[1], no = _c[0], nfl = _c[1], nfr = _c[2], configuration = _a[2], size = _a[3];
+            var background = _this._createBackground(cb);
+            var fovIndicator = _this._createFovIndicator(nfl, nfr, no);
+            var north = _this._createNorth(cb);
+            var cameraSector = _this._createCircleSectorCompass(_this._createCircleSector(Math.max(Math.PI / 20, cf), "#FFF"));
+            var compact = configuration.size === ComponentSize_1.default.Small ||
+                configuration.size === ComponentSize_1.default.Automatic && size.width < 640 ?
+                ".BearingCompact" : "";
             return {
                 name: _this._name,
-                vnode: vd.h("div.BearingIndicatorContainer", { oncontextmenu: function (event) { event.preventDefault(); } }, [
+                vnode: vd.h("div.BearingIndicatorContainer" + compact, { oncontextmenu: function (event) { event.preventDefault(); } }, [
                     background,
-                    backgroundCircle,
+                    fovIndicator,
                     north,
                     cameraSector,
                 ]),
@@ -23060,9 +30012,66 @@ var BearingComponent = /** @class */ (function (_super) {
     };
     BearingComponent.prototype._deactivate = function () {
         this._renderSubscription.unsubscribe();
+        this._fovSubscription.unsubscribe();
+        this._fovAnimationSubscription.unsubscribe();
     };
     BearingComponent.prototype._getDefaultConfiguration = function () {
-        return {};
+        return { size: ComponentSize_1.default.Automatic };
+    };
+    BearingComponent.prototype._createFovIndicator = function (fovLeft, fovRigth, offset) {
+        var arc = this._createFovArc(fovLeft, fovRigth);
+        var group = vd.h("g", {
+            attributes: { transform: "translate(18,18)" },
+            namespace: this._svgNamespace,
+        }, [arc]);
+        var svg = vd.h("svg", {
+            attributes: { viewBox: "0 0 36 36" },
+            namespace: this._svgNamespace,
+            style: {
+                height: "36px",
+                left: "2px",
+                position: "absolute",
+                top: "2px",
+                transform: "rotateZ(" + this._spatial.radToDeg(offset) + "deg)",
+                width: "36px",
+            },
+        }, [group]);
+        return svg;
+    };
+    BearingComponent.prototype._createFovArc = function (fovLeft, fovRigth) {
+        var radius = 16.75;
+        var strokeWidth = 2.5;
+        var fov = fovLeft + fovRigth;
+        if (fov > 2 * Math.PI - Math.PI / 90) {
+            return vd.h("circle", {
+                attributes: {
+                    cx: "0",
+                    cy: "0",
+                    "fill-opacity": "0",
+                    r: "" + radius,
+                    stroke: "#FFF",
+                    "stroke-width": "" + strokeWidth,
+                },
+                namespace: this._svgNamespace,
+            }, []);
+        }
+        var arcStart = -Math.PI / 2 - fovLeft;
+        var arcEnd = arcStart + fov;
+        var startX = radius * Math.cos(arcStart);
+        var startY = radius * Math.sin(arcStart);
+        var endX = radius * Math.cos(arcEnd);
+        var endY = radius * Math.sin(arcEnd);
+        var largeArc = fov >= Math.PI ? 1 : 0;
+        var description = "M " + startX + " " + startY + " A " + radius + " " + radius + " 0 " + largeArc + " 1 " + endX + " " + endY;
+        return vd.h("path", {
+            attributes: {
+                d: description,
+                "fill-opacity": "0",
+                stroke: "#FFF",
+                "stroke-width": "" + strokeWidth,
+            },
+            namespace: this._svgNamespace,
+        }, []);
     };
     BearingComponent.prototype._createCircleSectorCompass = function (cameraSector) {
         var group = vd.h("g", {
@@ -23073,11 +30082,11 @@ var BearingComponent = /** @class */ (function (_super) {
             attributes: { viewBox: "0 0 2 2" },
             namespace: this._svgNamespace,
             style: {
-                height: "30px",
-                left: "4px",
+                height: "26px",
+                left: "7px",
                 position: "absolute",
-                top: "4px",
-                width: "30px",
+                top: "7px",
+                width: "26px",
             },
         }, [group]);
         return svg;
@@ -23104,9 +30113,38 @@ var BearingComponent = /** @class */ (function (_super) {
     };
     BearingComponent.prototype._createNorth = function (bearing) {
         var north = vd.h("div.BearingNorth", []);
-        var container = vd.h("div.BearingNorthContainer", { style: { transform: "rotateZ(" + -bearing * 180 / Math.PI + "deg)" } }, [north]);
+        var container = vd.h("div.BearingNorthContainer", { style: { transform: "rotateZ(" + this._spatial.radToDeg(-bearing) + "deg)" } }, [north]);
         return container;
     };
+    BearingComponent.prototype._createBackground = function (bearing) {
+        return vd.h("div.BearingIndicatorBackground", { style: { transform: "rotateZ(" + this._spatial.radToDeg(-bearing) + "deg)" } }, [
+            vd.h("div.BearingIndicatorBackgroundCircle", []),
+            vd.h("div.BearingIndicatorBackgroundArrowContainer", [
+                vd.h("div.BearingIndicatorBackgroundArrow", []),
+            ]),
+        ]);
+    };
+    BearingComponent.prototype._computeProjectedPoints = function (transform) {
+        var vertices = [[1, 0]];
+        var directions = [[0, 0.5]];
+        var pointsPerLine = 12;
+        return Geo_1.Geo.computeProjectedPoints(transform, vertices, directions, pointsPerLine, this._viewportCoords);
+    };
+    BearingComponent.prototype._computeHorizontalFov = function (projectedPoints) {
+        var _this = this;
+        var fovs = projectedPoints
+            .map(function (projectedPoint) {
+            return _this._coordToFov(projectedPoint[0]);
+        });
+        var fov = Math.min.apply(Math, fovs);
+        return fov;
+    };
+    BearingComponent.prototype._coordToFov = function (x) {
+        return this._spatial.radToDeg(2 * Math.atan(x));
+    };
+    BearingComponent.prototype._interpolate = function (x1, x2, alpha) {
+        return (1 - alpha) * x1 + alpha * x2;
+    };
     BearingComponent.componentName = "bearing";
     return BearingComponent;
 }(Component_1.Component));
@@ -23114,7 +30152,8 @@ exports.BearingComponent = BearingComponent;
 Component_1.ComponentService.register(BearingComponent);
 exports.default = BearingComponent;
 
-},{"../Component":275,"../Geo":278,"rxjs/operators":225,"virtual-dom":231}],292:[function(require,module,exports){
+
+},{"../Component":291,"../Geo":294,"../geo/ViewportCoords":414,"./utils/ComponentSize":398,"@mapbox/unitbezier":2,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],308:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -23236,7 +30275,7 @@ exports.CacheComponent = CacheComponent;
 Component_1.ComponentService.register(CacheComponent);
 exports.default = CacheComponent;
 
-},{"../Component":275,"../Edge":276,"rxjs":27,"rxjs/operators":225}],293:[function(require,module,exports){
+},{"../Component":291,"../Edge":292,"rxjs":43,"rxjs/operators":241}],309:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -23362,7 +30401,7 @@ var Component = /** @class */ (function (_super) {
 exports.Component = Component;
 exports.default = Component;
 
-},{"../Utils":285,"rxjs":27,"rxjs/operators":225}],294:[function(require,module,exports){
+},{"../Utils":301,"rxjs":43,"rxjs/operators":241}],310:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Error_1 = require("../Error");
@@ -23463,7 +30502,7 @@ var ComponentService = /** @class */ (function () {
 exports.ComponentService = ComponentService;
 exports.default = ComponentService;
 
-},{"../Error":277}],295:[function(require,module,exports){
+},{"../Error":293}],311:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -23538,9 +30577,15 @@ var CoverComponent = /** @class */ (function (_super) {
     CoverComponent.prototype._getCoverButtonVNode = function (configuration) {
         var _this = this;
         var cover = configuration.state === Component_1.CoverState.Loading ? "div.Cover.CoverLoading" : "div.Cover";
-        var coverButton = vd.h("div.CoverButton", { onclick: function () { _this.configure({ state: Component_1.CoverState.Loading }); } }, [vd.h("div.CoverButtonIcon", [])]);
+        var coverButton = vd.h("div.CoverButton", [vd.h("div.CoverButtonIcon", [])]);
         var coverLogo = vd.h("a.CoverLogo", { href: Utils_1.Urls.explore, target: "_blank" }, []);
-        return vd.h(cover, [this._getCoverBackgroundVNode(configuration), coverButton, coverLogo]);
+        var coverIndicator = vd.h("div.CoverIndicator", { onclick: function () { _this.configure({ state: Component_1.CoverState.Loading }); } }, []);
+        return vd.h(cover, [
+            this._getCoverBackgroundVNode(configuration),
+            coverIndicator,
+            coverButton,
+            coverLogo,
+        ]);
     };
     CoverComponent.prototype._getCoverBackgroundVNode = function (conf) {
         var url = conf.src != null ?
@@ -23559,7 +30604,7 @@ exports.CoverComponent = CoverComponent;
 Component_1.ComponentService.registerCover(CoverComponent);
 exports.default = CoverComponent;
 
-},{"../Component":275,"../Utils":285,"../Viewer":286,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],296:[function(require,module,exports){
+},{"../Component":291,"../Utils":301,"../Viewer":302,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],312:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -23676,7 +30721,7 @@ exports.DebugComponent = DebugComponent;
 Component_1.ComponentService.register(DebugComponent);
 exports.default = DebugComponent;
 
-},{"../Component":275,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],297:[function(require,module,exports){
+},{"../Component":291,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],313:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -23747,7 +30792,7 @@ Component_1.ComponentService.register(ImageComponent);
 exports.default = ImageComponent;
 
 
-},{"../Component":275,"../Utils":285,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],298:[function(require,module,exports){
+},{"../Component":291,"../Utils":301,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],314:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -23825,7 +30870,7 @@ exports.LoadingComponent = LoadingComponent;
 Component_1.ComponentService.register(LoadingComponent);
 exports.default = LoadingComponent;
 
-},{"../Component":275,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],299:[function(require,module,exports){
+},{"../Component":291,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],315:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -23954,7 +30999,7 @@ exports.NavigationComponent = NavigationComponent;
 Component_1.ComponentService.register(NavigationComponent);
 exports.default = NavigationComponent;
 
-},{"../Component":275,"../Edge":276,"../Error":277,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],300:[function(require,module,exports){
+},{"../Component":291,"../Edge":292,"../Error":293,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],316:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -24176,7 +31221,7 @@ exports.RouteComponent = RouteComponent;
 Component_1.ComponentService.register(RouteComponent);
 exports.default = RouteComponent;
 
-},{"../Component":275,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],301:[function(require,module,exports){
+},{"../Component":291,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],317:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -24257,7 +31302,7 @@ exports.StatsComponent = StatsComponent;
 Component_1.ComponentService.register(StatsComponent);
 exports.default = StatsComponent;
 
-},{"../Component":275,"rxjs":27,"rxjs/operators":225}],302:[function(require,module,exports){
+},{"../Component":291,"rxjs":43,"rxjs/operators":241}],318:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -24438,7 +31483,7 @@ Component_1.ComponentService.register(DirectionComponent);
 exports.default = DirectionComponent;
 
 
-},{"../../Component":275,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],303:[function(require,module,exports){
+},{"../../Component":291,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],319:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Geo_1 = require("../../Geo");
@@ -24677,7 +31722,7 @@ exports.DirectionDOMCalculator = DirectionDOMCalculator;
 exports.default = DirectionDOMCalculator;
 
 
-},{"../../Geo":278}],304:[function(require,module,exports){
+},{"../../Geo":294}],320:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var vd = require("virtual-dom");
@@ -25057,7 +32102,7 @@ exports.DirectionDOMRenderer = DirectionDOMRenderer;
 exports.default = DirectionDOMRenderer;
 
 
-},{"../../Component":275,"../../Edge":276,"../../Error":277,"../../Geo":278,"virtual-dom":231}],305:[function(require,module,exports){
+},{"../../Component":291,"../../Edge":292,"../../Error":293,"../../Geo":294,"virtual-dom":247}],321:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -25076,9 +32121,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
 var operators_1 = require("rxjs/operators");
 var Component_1 = require("../../Component");
+var Viewer_1 = require("../../Viewer");
 var Render_1 = require("../../Render");
 var Tiles_1 = require("../../Tiles");
 var Utils_1 = require("../../Utils");
+var ViewportCoords_1 = require("../../geo/ViewportCoords");
+var Spatial_1 = require("../../geo/Spatial");
 var ImagePlaneComponent = /** @class */ (function (_super) {
     __extends(ImagePlaneComponent, _super);
     function ImagePlaneComponent(name, container, navigator) {
@@ -25196,10 +32244,16 @@ var ImagePlaneComponent = /** @class */ (function (_super) {
         this._setRegionOfInterestSubscription = textureProvider$.pipe(operators_1.switchMap(function (provider) {
             return roiTrigger$.pipe(operators_1.map(function (_a) {
                 var camera = _a[0], size = _a[1], transform = _a[2];
+                var basic = new ViewportCoords_1.default().viewportToBasic(0, 0, transform, camera.perspective);
+                if (basic[0] < 0 || basic[1] < 0 || basic[0] > 1 || basic[1] > 1) {
+                    return undefined;
+                }
                 return [
                     _this._roiCalculator.computeRegionOfInterest(camera, size, transform),
                     provider,
                 ];
+            }), operators_1.filter(function (args) {
+                return !!args;
             }));
         }), operators_1.filter(function (args) {
             return !args[1].disposed;
@@ -25260,6 +32314,92 @@ var ImagePlaneComponent = /** @class */ (function (_super) {
             };
         }))
             .subscribe(this._rendererOperation$);
+        this._clearPeripheryPlaneSubscription = this._navigator.panService.panNodes$.pipe(operators_1.filter(function (panNodes) {
+            return panNodes.length === 0;
+        }), operators_1.map(function () {
+            return function (renderer) {
+                renderer.clearPeripheryPlanes();
+                return renderer;
+            };
+        }))
+            .subscribe(this._rendererOperation$);
+        var cachedPanNodes$ = this._navigator.panService.panNodes$.pipe(operators_1.switchMap(function (nts) {
+            return rxjs_1.from(nts).pipe(operators_1.mergeMap(function (_a) {
+                var n = _a[0], t = _a[1];
+                return rxjs_1.combineLatest(_this._navigator.graphService.cacheNode$(n.key).pipe(operators_1.catchError(function (error) {
+                    console.error("Failed to cache periphery node (" + n.key + ")", error);
+                    return rxjs_1.empty();
+                })), rxjs_1.of(t));
+            }));
+        }), operators_1.share());
+        this._addPeripheryPlaneSubscription = cachedPanNodes$.pipe(operators_1.map(function (_a) {
+            var n = _a[0], t = _a[1];
+            return function (renderer) {
+                renderer.addPeripheryPlane(n, t);
+                return renderer;
+            };
+        }))
+            .subscribe(this._rendererOperation$);
+        this._updatePeripheryPlaneTextureSubscription = cachedPanNodes$.pipe(operators_1.mergeMap(function (_a) {
+            var n = _a[0];
+            return Viewer_1.ImageSize.Size2048 > Math.max(n.image.width, n.image.height) ?
+                n.cacheImage$(Viewer_1.ImageSize.Size2048).pipe(operators_1.catchError(function () {
+                    return rxjs_1.empty();
+                })) :
+                rxjs_1.empty();
+        }), operators_1.map(function (n) {
+            return function (renderer) {
+                renderer.updateTextureImage(n.image, n);
+                return renderer;
+            };
+        }))
+            .subscribe(this._rendererOperation$);
+        var inTransition$ = this._navigator.stateService.currentState$.pipe(operators_1.map(function (frame) {
+            return frame.state.alpha < 1;
+        }), operators_1.distinctUntilChanged());
+        var panTrigger$ = rxjs_1.combineLatest(this._container.mouseService.active$, this._container.touchService.active$, this._navigator.stateService.inMotion$, inTransition$).pipe(operators_1.map(function (_a) {
+            var mouseActive = _a[0], touchActive = _a[1], inMotion = _a[2], inTransition = _a[3];
+            return !(mouseActive || touchActive || inMotion || inTransition);
+        }), operators_1.filter(function (trigger) {
+            return trigger;
+        }));
+        this._moveToPeripheryNodeSubscription = this._navigator.panService.panNodes$.pipe(operators_1.switchMap(function (nts) {
+            return panTrigger$.pipe(operators_1.withLatestFrom(_this._container.renderService.renderCamera$, _this._navigator.stateService.currentNode$, _this._navigator.stateService.currentTransform$), operators_1.mergeMap(function (_a) {
+                var renderCamera = _a[1], currentNode = _a[2], currentTransform = _a[3];
+                return rxjs_1.of([
+                    renderCamera,
+                    currentNode,
+                    currentTransform,
+                    nts,
+                ]);
+            }));
+        }), operators_1.switchMap(function (_a) {
+            var camera = _a[0], cn = _a[1], ct = _a[2], nts = _a[3];
+            var direction = camera.camera.lookat.clone().sub(camera.camera.position);
+            var cd = new Spatial_1.default().viewingDirection(cn.rotation);
+            var ca = cd.angleTo(direction);
+            var closest = [ca, undefined];
+            var basic = new ViewportCoords_1.default().viewportToBasic(0, 0, ct, camera.perspective);
+            if (basic[0] >= 0 && basic[0] <= 1 && basic[1] >= 0 && basic[1] <= 1) {
+                closest[0] = Number.NEGATIVE_INFINITY;
+            }
+            for (var _i = 0, nts_1 = nts; _i < nts_1.length; _i++) {
+                var n = nts_1[_i][0];
+                var d = new Spatial_1.default().viewingDirection(n.rotation);
+                var a = d.angleTo(direction);
+                if (a < closest[0]) {
+                    closest[0] = a;
+                    closest[1] = n.key;
+                }
+            }
+            if (!closest[1]) {
+                return rxjs_1.empty();
+            }
+            return _this._navigator.moveToKey$(closest[1]).pipe(operators_1.catchError(function () {
+                return rxjs_1.empty();
+            }));
+        }))
+            .subscribe();
     };
     ImagePlaneComponent.prototype._deactivate = function () {
         this._rendererDisposer$.next(null);
@@ -25273,6 +32413,10 @@ var ImagePlaneComponent = /** @class */ (function (_super) {
         this._textureProviderSubscription.unsubscribe();
         this._updateBackgroundSubscription.unsubscribe();
         this._updateTextureImageSubscription.unsubscribe();
+        this._clearPeripheryPlaneSubscription.unsubscribe();
+        this._addPeripheryPlaneSubscription.unsubscribe();
+        this._updatePeripheryPlaneTextureSubscription.unsubscribe();
+        this._moveToPeripheryNodeSubscription.unsubscribe();
     };
     ImagePlaneComponent.prototype._getDefaultConfiguration = function () {
         return {};
@@ -25284,7 +32428,7 @@ exports.ImagePlaneComponent = ImagePlaneComponent;
 Component_1.ComponentService.register(ImagePlaneComponent);
 exports.default = ImagePlaneComponent;
 
-},{"../../Component":275,"../../Render":281,"../../Tiles":284,"../../Utils":285,"rxjs":27,"rxjs/operators":225}],306:[function(require,module,exports){
+},{"../../Component":291,"../../Render":297,"../../Tiles":300,"../../Utils":301,"../../Viewer":302,"../../geo/Spatial":412,"../../geo/ViewportCoords":414,"rxjs":43,"rxjs/operators":241}],322:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Component_1 = require("../../Component");
@@ -25318,6 +32462,17 @@ var ImagePlaneGLRenderer = /** @class */ (function () {
     ImagePlaneGLRenderer.prototype.indicateNeedsRender = function () {
         this._needsRender = true;
     };
+    ImagePlaneGLRenderer.prototype.addPeripheryPlane = function (node, transform) {
+        var mesh = this._factory.createMesh(node, transform);
+        var planes = {};
+        planes[node.key] = mesh;
+        this._scene.addPeripheryPlanes(planes);
+        this._needsRender = true;
+    };
+    ImagePlaneGLRenderer.prototype.clearPeripheryPlanes = function () {
+        this._scene.setPeripheryPlanes({});
+        this._needsRender = true;
+    };
     ImagePlaneGLRenderer.prototype.updateFrame = function (frame) {
         this._updateFrameId(frame.id);
         this._needsRender = this._updateAlpha(frame.state.alpha) || this._needsRender;
@@ -25349,24 +32504,17 @@ var ImagePlaneGLRenderer = /** @class */ (function () {
         }
         this._providerDisposers[key] = dispose;
     };
-    ImagePlaneGLRenderer.prototype._updateTexture = function (texture) {
-        this._needsRender = true;
-        for (var _i = 0, _a = this._scene.imagePlanes; _i < _a.length; _i++) {
-            var plane = _a[_i];
-            var material = plane.material;
-            var oldTexture = material.uniforms.projectorTex.value;
-            material.uniforms.projectorTex.value = null;
-            oldTexture.dispose();
-            material.uniforms.projectorTex.value = texture;
-        }
-    };
     ImagePlaneGLRenderer.prototype.updateTextureImage = function (image, node) {
-        if (this._currentKey !== node.key) {
-            return;
-        }
         this._needsRender = true;
-        for (var _i = 0, _a = this._scene.imagePlanes; _i < _a.length; _i++) {
-            var plane = _a[_i];
+        var planes = this._extend({}, this._scene.planes, this._scene.planesOld, this._scene.planesPeriphery);
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            if (key !== node.key) {
+                continue;
+            }
+            var plane = planes[key];
             var material = plane.material;
             var texture = material.uniforms.projectorTex.value;
             texture.image = image;
@@ -25374,19 +32522,40 @@ var ImagePlaneGLRenderer = /** @class */ (function () {
         }
     };
     ImagePlaneGLRenderer.prototype.render = function (perspectiveCamera, renderer) {
-        var planeAlpha = this._scene.imagePlanesOld.length ? 1 : this._alpha;
-        for (var _i = 0, _a = this._scene.imagePlanes; _i < _a.length; _i++) {
-            var plane = _a[_i];
+        var planes = this._scene.planes;
+        var planesOld = this._scene.planesOld;
+        var planesPeriphery = this._scene.planesPeriphery;
+        var planeAlpha = Object.keys(planesOld).length ? 1 : this._alpha;
+        var peripheryAlpha = Object.keys(planesOld).length ? 1 : Math.floor(this._alpha);
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
             plane.material.uniforms.opacity.value = planeAlpha;
         }
-        for (var _b = 0, _c = this._scene.imagePlanesOld; _b < _c.length; _b++) {
-            var plane = _c[_b];
+        for (var key in planesOld) {
+            if (!planesOld.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planesOld[key];
             plane.material.uniforms.opacity.value = this._alphaOld;
         }
+        for (var key in planesPeriphery) {
+            if (!planesPeriphery.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planesPeriphery[key];
+            plane.material.uniforms.opacity.value = peripheryAlpha;
+        }
+        renderer.render(this._scene.scenePeriphery, perspectiveCamera);
         renderer.render(this._scene.scene, perspectiveCamera);
         renderer.render(this._scene.sceneOld, perspectiveCamera);
-        for (var _d = 0, _e = this._scene.imagePlanes; _d < _e.length; _d++) {
-            var plane = _e[_d];
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
             plane.material.uniforms.opacity.value = this._alpha;
         }
         renderer.render(this._scene.scene, perspectiveCamera);
@@ -25430,22 +32599,57 @@ var ImagePlaneGLRenderer = /** @class */ (function () {
         if (previousKey != null) {
             if (previousKey !== this._currentKey && previousKey !== this._previousKey) {
                 var previousMesh = this._factory.createMesh(state.previousNode, state.previousTransform);
-                this._scene.updateImagePlanes([previousMesh]);
+                var previousPlanes = {};
+                previousPlanes[previousKey] = previousMesh;
+                this._scene.updateImagePlanes(previousPlanes);
             }
             this._previousKey = previousKey;
         }
         this._currentKey = currentKey;
         var currentMesh = this._factory.createMesh(state.currentNode, state.currentTransform);
-        this._scene.updateImagePlanes([currentMesh]);
+        var planes = {};
+        planes[currentKey] = currentMesh;
+        this._scene.updateImagePlanes(planes);
         this._alphaOld = 1;
         return true;
     };
+    ImagePlaneGLRenderer.prototype._updateTexture = function (texture) {
+        this._needsRender = true;
+        var planes = this._scene.planes;
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
+            var material = plane.material;
+            var oldTexture = material.uniforms.projectorTex.value;
+            material.uniforms.projectorTex.value = null;
+            oldTexture.dispose();
+            material.uniforms.projectorTex.value = texture;
+        }
+    };
+    ImagePlaneGLRenderer.prototype._extend = function (dest) {
+        var sources = [];
+        for (var _i = 1; _i < arguments.length; _i++) {
+            sources[_i - 1] = arguments[_i];
+        }
+        for (var _a = 0, sources_1 = sources; _a < sources_1.length; _a++) {
+            var src = sources_1[_a];
+            for (var k in src) {
+                if (!src.hasOwnProperty(k)) {
+                    continue;
+                }
+                dest[k] = src[k];
+            }
+        }
+        return dest;
+    };
     return ImagePlaneGLRenderer;
 }());
 exports.ImagePlaneGLRenderer = ImagePlaneGLRenderer;
 exports.default = ImagePlaneGLRenderer;
 
-},{"../../Component":275}],307:[function(require,module,exports){
+},{"../../Component":291}],323:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var CoverState;
@@ -25455,7 +32659,7 @@ var CoverState;
     CoverState[CoverState["Visible"] = 2] = "Visible";
 })(CoverState = exports.CoverState || (exports.CoverState = {}));
 
-},{}],308:[function(require,module,exports){
+},{}],324:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -25495,7 +32699,7 @@ var SliderMode;
     SliderMode[SliderMode["Stationary"] = 1] = "Stationary";
 })(SliderMode = exports.SliderMode || (exports.SliderMode = {}));
 
-},{}],309:[function(require,module,exports){
+},{}],325:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var ICoverConfiguration_1 = require("./ICoverConfiguration");
@@ -25503,7 +32707,7 @@ exports.CoverState = ICoverConfiguration_1.CoverState;
 var ISliderConfiguration_1 = require("./ISliderConfiguration");
 exports.SliderMode = ISliderConfiguration_1.SliderMode;
 
-},{"./ICoverConfiguration":307,"./ISliderConfiguration":308}],310:[function(require,module,exports){
+},{"./ICoverConfiguration":323,"./ISliderConfiguration":324}],326:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -25608,7 +32812,7 @@ var KeyPlayHandler = /** @class */ (function (_super) {
 exports.KeyPlayHandler = KeyPlayHandler;
 exports.default = KeyPlayHandler;
 
-},{"../../Component":275,"../../Edge":276,"rxjs/operators":225}],311:[function(require,module,exports){
+},{"../../Component":291,"../../Edge":292,"rxjs/operators":241}],327:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -25698,7 +32902,7 @@ var KeySequenceNavigationHandler = /** @class */ (function (_super) {
 exports.KeySequenceNavigationHandler = KeySequenceNavigationHandler;
 exports.default = KeySequenceNavigationHandler;
 
-},{"../../Component":275,"../../Edge":276,"../../Error":277,"rxjs/operators":225}],312:[function(require,module,exports){
+},{"../../Component":291,"../../Edge":292,"../../Error":293,"rxjs/operators":241}],328:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -25847,7 +33051,7 @@ var KeySpatialNavigationHandler = /** @class */ (function (_super) {
 exports.KeySpatialNavigationHandler = KeySpatialNavigationHandler;
 exports.default = KeySpatialNavigationHandler;
 
-},{"../../Component":275,"../../Edge":276,"../../Error":277,"rxjs/operators":225}],313:[function(require,module,exports){
+},{"../../Component":291,"../../Edge":292,"../../Error":293,"rxjs/operators":241}],329:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -25926,7 +33130,7 @@ var KeyZoomHandler = /** @class */ (function (_super) {
 exports.KeyZoomHandler = KeyZoomHandler;
 exports.default = KeyZoomHandler;
 
-},{"../../Component":275,"rxjs/operators":225}],314:[function(require,module,exports){
+},{"../../Component":291,"rxjs/operators":241}],330:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -26067,7 +33271,7 @@ exports.KeyboardComponent = KeyboardComponent;
 Component_1.ComponentService.register(KeyboardComponent);
 exports.default = KeyboardComponent;
 
-},{"../../Component":275,"../../Geo":278}],315:[function(require,module,exports){
+},{"../../Component":291,"../../Geo":294}],331:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var MarkerComponent_1 = require("./MarkerComponent");
@@ -26077,7 +33281,7 @@ exports.SimpleMarker = SimpleMarker_1.SimpleMarker;
 var CircleMarker_1 = require("./marker/CircleMarker");
 exports.CircleMarker = CircleMarker_1.CircleMarker;
 
-},{"./MarkerComponent":316,"./marker/CircleMarker":319,"./marker/SimpleMarker":321}],316:[function(require,module,exports){
+},{"./MarkerComponent":332,"./marker/CircleMarker":335,"./marker/SimpleMarker":337}],332:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -26515,7 +33719,7 @@ Component_1.ComponentService.register(MarkerComponent);
 exports.default = MarkerComponent;
 
 
-},{"../../Component":275,"../../Geo":278,"../../Graph":279,"../../Render":281,"rxjs":27,"rxjs/operators":225,"three":226,"when":272}],317:[function(require,module,exports){
+},{"../../Component":291,"../../Geo":294,"../../Graph":295,"../../Render":297,"rxjs":43,"rxjs/operators":241,"three":242,"when":288}],333:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
@@ -26637,7 +33841,7 @@ var MarkerScene = /** @class */ (function () {
 exports.MarkerScene = MarkerScene;
 exports.default = MarkerScene;
 
-},{"three":226}],318:[function(require,module,exports){
+},{"three":242}],334:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rbush = require("rbush");
@@ -26754,7 +33958,7 @@ var MarkerSet = /** @class */ (function () {
 exports.MarkerSet = MarkerSet;
 exports.default = MarkerSet;
 
-},{"rbush":26,"rxjs":27}],319:[function(require,module,exports){
+},{"rbush":42,"rxjs":43}],335:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -26839,7 +34043,7 @@ var CircleMarker = /** @class */ (function (_super) {
 exports.CircleMarker = CircleMarker;
 exports.default = CircleMarker;
 
-},{"../../../Component":275,"three":226}],320:[function(require,module,exports){
+},{"../../../Component":291,"three":242}],336:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -26935,7 +34139,7 @@ var Marker = /** @class */ (function () {
 exports.Marker = Marker;
 exports.default = Marker;
 
-},{}],321:[function(require,module,exports){
+},{}],337:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -27084,7 +34288,7 @@ var SimpleMarker = /** @class */ (function (_super) {
 exports.SimpleMarker = SimpleMarker;
 exports.default = SimpleMarker;
 
-},{"../../../Component":275,"three":226}],322:[function(require,module,exports){
+},{"../../../Component":291,"three":242}],338:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -27119,16 +34323,16 @@ var BounceHandler = /** @class */ (function (_super) {
         var _this = this;
         var inTransition$ = this._navigator.stateService.currentState$.pipe(operators_1.map(function (frame) {
             return frame.state.alpha < 1;
-        }));
+        }), operators_1.distinctUntilChanged());
         this._bounceSubscription = rxjs_1.combineLatest(inTransition$, this._navigator.stateService.inTranslation$, this._container.mouseService.active$, this._container.touchService.active$).pipe(operators_1.map(function (noForce) {
             return noForce[0] || noForce[1] || noForce[2] || noForce[3];
         }), operators_1.distinctUntilChanged(), operators_1.switchMap(function (noForce) {
             return noForce ?
                 rxjs_1.empty() :
                 rxjs_1.combineLatest(_this._container.renderService.renderCamera$, _this._navigator.stateService.currentTransform$.pipe(operators_1.first()));
-        }))
+        }), operators_1.withLatestFrom(this._navigator.panService.panNodes$))
             .subscribe(function (_a) {
-            var render = _a[0], transform = _a[1];
+            var _b = _a[0], render = _b[0], transform = _b[1], nts = _a[1];
             if (!transform.hasValidScale && render.camera.focal < 0.1) {
                 return;
             }
@@ -27136,6 +34340,19 @@ var BounceHandler = /** @class */ (function (_super) {
                 return;
             }
             var distances = Component_1.ImageBoundary.viewportDistances(transform, render.perspective, _this._viewportCoords);
+            var basic = _this._viewportCoords.viewportToBasic(0, 0, transform, render.perspective);
+            if ((basic[0] < 0 || basic[0] > 1) && nts.length > 0) {
+                distances[0] = distances[2] = 0;
+            }
+            for (var _i = 0, nts_1 = nts; _i < nts_1.length; _i++) {
+                var _c = nts_1[_i], t = _c[1];
+                var d = Component_1.ImageBoundary.viewportDistances(t, render.perspective, _this._viewportCoords);
+                for (var i = 1; i < distances.length; i += 2) {
+                    if (d[i] < distances[i]) {
+                        distances[i] = d[i];
+                    }
+                }
+            }
             if (Math.max.apply(Math, distances) < 0.01) {
                 return;
             }
@@ -27170,7 +34387,7 @@ var BounceHandler = /** @class */ (function (_super) {
 exports.BounceHandler = BounceHandler;
 exports.default = BounceHandler;
 
-},{"../../Component":275,"rxjs":27,"rxjs/operators":225}],323:[function(require,module,exports){
+},{"../../Component":291,"rxjs":43,"rxjs/operators":241}],339:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -27238,7 +34455,7 @@ var DoubleClickZoomHandler = /** @class */ (function (_super) {
 exports.DoubleClickZoomHandler = DoubleClickZoomHandler;
 exports.default = DoubleClickZoomHandler;
 
-},{"../../Component":275,"rxjs":27,"rxjs/operators":225}],324:[function(require,module,exports){
+},{"../../Component":291,"rxjs":43,"rxjs/operators":241}],340:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -27322,8 +34539,8 @@ var DragPanHandler = /** @class */ (function (_super) {
                 return pair[0] != null && pair[1] != null;
             }));
             return rxjs_1.merge(mouseDrag$, singleTouchDrag$);
-        }), operators_1.withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$), operators_1.map(function (_a) {
-            var events = _a[0], render = _a[1], transform = _a[2];
+        }), operators_1.withLatestFrom(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$, this._navigator.panService.panNodes$), operators_1.map(function (_a) {
+            var events = _a[0], render = _a[1], transform = _a[2], nts = _a[3];
             var previousEvent = events[0];
             var event = events[1];
             var movementX = event.clientX - previousEvent.clientX;
@@ -27339,6 +34556,15 @@ var DragPanHandler = /** @class */ (function (_super) {
             var phi = (movementX > 0 ? 1 : -1) * directionX.angleTo(currentDirection);
             var theta = (movementY > 0 ? -1 : 1) * directionY.angleTo(currentDirection);
             var distances = Component_1.ImageBoundary.viewportDistances(transform, render.perspective, _this._viewportCoords);
+            for (var _i = 0, nts_1 = nts; _i < nts_1.length; _i++) {
+                var _c = nts_1[_i], t = _c[1];
+                var d = Component_1.ImageBoundary.viewportDistances(t, render.perspective, _this._viewportCoords);
+                for (var i = 0; i < distances.length; i++) {
+                    if (d[i] < distances[i]) {
+                        distances[i] = d[i];
+                    }
+                }
+            }
             if (distances[0] > 0 && theta < 0) {
                 theta /= Math.max(1, 2e2 * distances[0]);
             }
@@ -27410,7 +34636,7 @@ var DragPanHandler = /** @class */ (function (_super) {
 exports.DragPanHandler = DragPanHandler;
 exports.default = DragPanHandler;
 
-},{"../../Component":275,"rxjs":27,"rxjs/operators":225}],325:[function(require,module,exports){
+},{"../../Component":291,"rxjs":43,"rxjs/operators":241}],341:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -27558,7 +34784,7 @@ var EarthControlHandler = /** @class */ (function (_super) {
 exports.EarthControlHandler = EarthControlHandler;
 exports.default = EarthControlHandler;
 
-},{"../../Component":275,"../../State":282,"rxjs":27,"rxjs/operators":225,"three":226}],326:[function(require,module,exports){
+},{"../../Component":291,"../../State":298,"rxjs":43,"rxjs/operators":241,"three":242}],342:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Geo_1 = require("../../../src/Geo");
@@ -27675,7 +34901,7 @@ function viewportDistances(transform, perspective, viewportCoords) {
 }
 exports.viewportDistances = viewportDistances;
 
-},{"../../../src/Geo":278}],327:[function(require,module,exports){
+},{"../../../src/Geo":294}],343:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -27827,7 +35053,7 @@ exports.MouseComponent = MouseComponent;
 Component_1.ComponentService.register(MouseComponent);
 exports.default = MouseComponent;
 
-},{"../../Component":275,"../../Geo":278}],328:[function(require,module,exports){
+},{"../../Component":291,"../../Geo":294}],344:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -27919,7 +35145,7 @@ var ScrollZoomHandler = /** @class */ (function (_super) {
 exports.ScrollZoomHandler = ScrollZoomHandler;
 exports.default = ScrollZoomHandler;
 
-},{"../../Component":275,"rxjs/operators":225}],329:[function(require,module,exports){
+},{"../../Component":291,"rxjs/operators":241}],345:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -28005,7 +35231,7 @@ var TouchZoomHandler = /** @class */ (function (_super) {
 exports.TouchZoomHandler = TouchZoomHandler;
 exports.default = TouchZoomHandler;
 
-},{"../../Component":275,"rxjs":27,"rxjs/operators":225}],330:[function(require,module,exports){
+},{"../../Component":291,"rxjs":43,"rxjs/operators":241}],346:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Popup_1 = require("./popup/Popup");
@@ -28013,7 +35239,7 @@ exports.Popup = Popup_1.Popup;
 var PopupComponent_1 = require("./PopupComponent");
 exports.PopupComponent = PopupComponent_1.PopupComponent;
 
-},{"./PopupComponent":331,"./popup/Popup":332}],331:[function(require,module,exports){
+},{"./PopupComponent":347,"./popup/Popup":348}],347:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -28193,7 +35419,7 @@ exports.PopupComponent = PopupComponent;
 Component_1.ComponentService.register(PopupComponent);
 exports.default = PopupComponent;
 
-},{"../../Component":275,"../../Utils":285,"rxjs":27,"rxjs/operators":225}],332:[function(require,module,exports){
+},{"../../Component":291,"../../Utils":301,"rxjs":43,"rxjs/operators":241}],348:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -28675,7 +35901,7 @@ exports.Popup = Popup;
 exports.default = Popup;
 
 
-},{"../../../Geo":278,"../../../Utils":285,"../../../Viewer":286,"rxjs":27}],333:[function(require,module,exports){
+},{"../../../Geo":294,"../../../Utils":301,"../../../Viewer":302,"rxjs":43}],349:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -29016,7 +36242,7 @@ exports.SequenceComponent = SequenceComponent;
 Component_1.ComponentService.register(SequenceComponent);
 exports.default = SequenceComponent;
 
-},{"../../Component":275,"../../Edge":276,"../../Graph":279,"rxjs":27,"rxjs/operators":225}],334:[function(require,module,exports){
+},{"../../Component":291,"../../Edge":292,"../../Graph":295,"rxjs":43,"rxjs/operators":241}],350:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -29445,7 +36671,7 @@ var SequenceDOMRenderer = /** @class */ (function () {
 exports.SequenceDOMRenderer = SequenceDOMRenderer;
 exports.default = SequenceDOMRenderer;
 
-},{"../../Component":275,"../../Edge":276,"../../Error":277,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],335:[function(require,module,exports){
+},{"../../Component":291,"../../Edge":292,"../../Error":293,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],351:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var SequenceMode;
@@ -29456,7 +36682,7 @@ var SequenceMode;
 })(SequenceMode = exports.SequenceMode || (exports.SequenceMode = {}));
 exports.default = SequenceMode;
 
-},{}],336:[function(require,module,exports){
+},{}],352:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 
@@ -29501,7 +36727,7 @@ var Shaders = /** @class */ (function () {
 exports.Shaders = Shaders;
 
 
-},{"path":23}],337:[function(require,module,exports){
+},{"path":39}],353:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -29535,7 +36761,7 @@ var Utils_1 = require("../../Utils");
  * components when activating the slider component to avoid
  * interfering UI elements.
  *
- * To retrive and use the marker component
+ * To retrive and use the slider component
  *
  * @example
  * ```
@@ -29550,7 +36776,7 @@ var Utils_1 = require("../../Utils");
  *
  * viewer.activateComponent("slider");
  *
- * var sliderComponent = viewer.getComponent("marker");
+ * var sliderComponent = viewer.getComponent("slider");
  * ```
  */
 var SliderComponent = /** @class */ (function (_super) {
@@ -30181,7 +37407,7 @@ Component_1.ComponentService.register(SliderComponent);
 exports.default = SliderComponent;
 
 
-},{"../../Component":275,"../../Geo":278,"../../Render":281,"../../State":282,"../../Tiles":284,"../../Utils":285,"rxjs":27,"rxjs/operators":225}],338:[function(require,module,exports){
+},{"../../Component":291,"../../Geo":294,"../../Render":297,"../../State":298,"../../Tiles":300,"../../Utils":301,"rxjs":43,"rxjs/operators":241}],354:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -30239,6 +37465,7 @@ var SliderDOMRenderer = /** @class */ (function () {
             var modeVisible = !(motionless || pano);
             if (modeVisible) {
                 children.push(this._createModeButton(mode));
+                children.push(this._createModeButton2d(mode));
             }
             children.push(this._createPositionInput(position, modeVisible));
         }
@@ -30250,16 +37477,32 @@ var SliderDOMRenderer = /** @class */ (function () {
         var _this = this;
         var properties = {
             onclick: function () {
-                _this._notifyModeChanged$.next(mode === Component_1.SliderMode.Motion ?
-                    Component_1.SliderMode.Stationary :
-                    Component_1.SliderMode.Motion);
+                if (mode === Component_1.SliderMode.Motion) {
+                    return;
+                }
+                _this._notifyModeChanged$.next(Component_1.SliderMode.Motion);
             },
         };
         var className = mode === Component_1.SliderMode.Stationary ?
-            "SliderModeButtonPressed" :
+            "SliderModeButtonDisabled" :
             "SliderModeButton";
         return vd.h("div." + className, properties, [vd.h("div.SliderModeIcon", [])]);
     };
+    SliderDOMRenderer.prototype._createModeButton2d = function (mode) {
+        var _this = this;
+        var properties = {
+            onclick: function () {
+                if (mode === Component_1.SliderMode.Stationary) {
+                    return;
+                }
+                _this._notifyModeChanged$.next(Component_1.SliderMode.Stationary);
+            },
+        };
+        var className = mode === Component_1.SliderMode.Motion ?
+            "SliderModeButton2dDisabled" :
+            "SliderModeButton2d";
+        return vd.h("div." + className, properties, [vd.h("div.SliderModeIcon2d", [])]);
+    };
     SliderDOMRenderer.prototype._createPositionInput = function (position, modeVisible) {
         var _this = this;
         var onChange = function (e) {
@@ -30281,7 +37524,7 @@ var SliderDOMRenderer = /** @class */ (function () {
             }
         };
         var boundingRect = this._container.domContainer.getBoundingClientRect();
-        var width = Math.max(215, Math.min(400, boundingRect.width - 105)) - 68 + (modeVisible ? 0 : 36);
+        var width = Math.max(215, Math.min(400, boundingRect.width - 105)) - 84 + (modeVisible ? 0 : 52);
         var positionInput = vd.h("input.SliderPosition", {
             max: 1000,
             min: 0,
@@ -30305,7 +37548,7 @@ var SliderDOMRenderer = /** @class */ (function () {
 exports.SliderDOMRenderer = SliderDOMRenderer;
 exports.default = SliderDOMRenderer;
 
-},{"../../Component":275,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],339:[function(require,module,exports){
+},{"../../Component":291,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],355:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Component_1 = require("../../Component");
@@ -30365,17 +37608,20 @@ var SliderGLRenderer = /** @class */ (function () {
         this._needsRender = true;
     };
     SliderGLRenderer.prototype.updateTexture = function (image, node) {
-        var imagePlanes = node.key === this._currentKey ?
-            this._scene.imagePlanes :
+        var planes = node.key === this._currentKey ?
+            this._scene.planes :
             node.key === this._previousKey ?
-                this._scene.imagePlanesOld :
-                [];
-        if (imagePlanes.length === 0) {
+                this._scene.planesOld :
+                {};
+        if (Object.keys(planes).length === 0) {
             return;
         }
         this._needsRender = true;
-        for (var _i = 0, imagePlanes_1 = imagePlanes; _i < imagePlanes_1.length; _i++) {
-            var plane = imagePlanes_1[_i];
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
             var material = plane.material;
             var texture = material.uniforms.projectorTex.value;
             texture.image = image;
@@ -30387,8 +37633,12 @@ var SliderGLRenderer = /** @class */ (function () {
             return;
         }
         this._needsRender = true;
-        for (var _i = 0, _a = this._scene.imagePlanes; _i < _a.length; _i++) {
-            var plane = _a[_i];
+        var planes = this._scene.planes;
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
             var material = plane.material;
             var texture = material.uniforms.projectorTex.value;
             texture.image = image;
@@ -30463,8 +37713,12 @@ var SliderGLRenderer = /** @class */ (function () {
         providerDisposers[key] = dispose;
     };
     SliderGLRenderer.prototype._updateCurtain = function () {
-        for (var _i = 0, _a = this._scene.imagePlanes; _i < _a.length; _i++) {
-            var plane = _a[_i];
+        var planes = this._scene.planes;
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
             var shaderMaterial = plane.material;
             if (!!shaderMaterial.uniforms.curtain) {
                 shaderMaterial.uniforms.curtain.value = this._curtain;
@@ -30492,7 +37746,7 @@ var SliderGLRenderer = /** @class */ (function () {
             }
         }
         if (this.disabled) {
-            this._scene.setImagePlanesOld([]);
+            this._scene.setImagePlanesOld({});
         }
         else {
             if (previousChanged || modeChanged) {
@@ -30533,7 +37787,9 @@ var SliderGLRenderer = /** @class */ (function () {
                         mesh = this._factory.createMesh(state.previousNode, state.previousTransform);
                     }
                 }
-                this._scene.setImagePlanesOld([mesh]);
+                var previousPlanes = {};
+                previousPlanes[previousNode.key] = mesh;
+                this._scene.setImagePlanesOld(previousPlanes);
             }
         }
         if (currentChanged || modeChanged) {
@@ -30542,29 +37798,33 @@ var SliderGLRenderer = /** @class */ (function () {
                 delete this._currentProviderDisposers[this._currentKey];
             }
             this._currentKey = state.currentNode.key;
-            var imagePlanes = [];
+            var planes = {};
             if (state.currentNode.fullPano) {
-                imagePlanes.push(this._factory.createCurtainMesh(state.currentNode, state.currentTransform));
+                planes[state.currentNode.key] = this._factory.createCurtainMesh(state.currentNode, state.currentTransform);
             }
             else if (state.currentNode.pano && !state.currentNode.fullPano) {
-                imagePlanes.push(this._factory.createMesh(state.currentNode, state.currentTransform));
+                planes[state.currentNode.key] = this._factory.createMesh(state.currentNode, state.currentTransform);
             }
             else {
                 if (motionless) {
-                    imagePlanes.push(this._factory.createDistortedCurtainMesh(state.currentNode, state.currentTransform));
+                    planes[state.currentNode.key] = this._factory.createDistortedCurtainMesh(state.currentNode, state.currentTransform);
                 }
                 else {
-                    imagePlanes.push(this._factory.createCurtainMesh(state.currentNode, state.currentTransform));
+                    planes[state.currentNode.key] = this._factory.createCurtainMesh(state.currentNode, state.currentTransform);
                 }
             }
-            this._scene.setImagePlanes(imagePlanes);
+            this._scene.setImagePlanes(planes);
             this._updateCurtain();
         }
     };
     SliderGLRenderer.prototype._updateTexture = function (texture) {
         this._needsRender = true;
-        for (var _i = 0, _a = this._scene.imagePlanes; _i < _a.length; _i++) {
-            var plane = _a[_i];
+        var planes = this._scene.planes;
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
             var material = plane.material;
             var oldTexture = material.uniforms.projectorTex.value;
             material.uniforms.projectorTex.value = null;
@@ -30574,8 +37834,12 @@ var SliderGLRenderer = /** @class */ (function () {
     };
     SliderGLRenderer.prototype._updateTexturePrev = function (texture) {
         this._needsRender = true;
-        for (var _i = 0, _a = this._scene.imagePlanesOld; _i < _a.length; _i++) {
-            var plane = _a[_i];
+        var planes = this._scene.planesOld;
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
             var material = plane.material;
             var oldTexture = material.uniforms.projectorTex.value;
             material.uniforms.projectorTex.value = null;
@@ -30589,10 +37853,29 @@ exports.SliderGLRenderer = SliderGLRenderer;
 exports.default = SliderGLRenderer;
 
 
-},{"../../Component":275,"../../Geo":278}],340:[function(require,module,exports){
+},{"../../Component":291,"../../Geo":294}],356:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var CameraVisualizationMode;
+(function (CameraVisualizationMode) {
+    CameraVisualizationMode[CameraVisualizationMode["Default"] = 0] = "Default";
+    CameraVisualizationMode[CameraVisualizationMode["Cluster"] = 1] = "Cluster";
+    CameraVisualizationMode[CameraVisualizationMode["ConnectedComponent"] = 2] = "ConnectedComponent";
+    CameraVisualizationMode[CameraVisualizationMode["Sequence"] = 3] = "Sequence";
+})(CameraVisualizationMode = exports.CameraVisualizationMode || (exports.CameraVisualizationMode = {}));
+exports.default = CameraVisualizationMode;
+
+},{}],357:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var CameraVisualizationMode_1 = require("./CameraVisualizationMode");
+exports.CameraVisualizationMode = CameraVisualizationMode_1.CameraVisualizationMode;
+
+},{"./CameraVisualizationMode":356}],358:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var geohash = require("latlon-geohash");
+var pako = require("pako");
 var rxjs_1 = require("rxjs");
 var operators_1 = require("rxjs/operators");
 var Error_1 = require("../../Error");
@@ -30602,68 +37885,68 @@ var SpatialDataCache = /** @class */ (function () {
         this._graphService = graphService;
         this._tiles = {};
         this._cacheRequests = {};
-        this._reconstructions = {};
-        this._cachingReconstructions$ = {};
+        this._clusterReconstructions = {};
+        this._clusterReconstructionTiles = {};
+        this._tileClusters = {};
         this._cachingTiles$ = {};
+        this._cachingClusterReconstructions$ = {};
     }
-    SpatialDataCache.prototype.cacheReconstructions$ = function (hash) {
+    SpatialDataCache.prototype.cacheClusterReconstructions$ = function (hash) {
         var _this = this;
         if (!this.hasTile(hash)) {
             throw new Error("Cannot cache reconstructions of a non-existing tile.");
         }
-        if (this.hasReconstructions(hash)) {
+        if (this.hasClusterReconstructions(hash)) {
             throw new Error("Cannot cache reconstructions that already exists.");
         }
-        if (this.isCachingReconstructions(hash)) {
-            return this._cachingReconstructions$[hash];
+        if (this.isCachingClusterReconstructions(hash)) {
+            return this._cachingClusterReconstructions$[hash];
         }
-        var tile = [];
-        if (hash in this._reconstructions) {
-            var reconstructionKeys = this.getReconstructions(hash)
-                .map(function (reconstruction) {
-                return reconstruction.data.key;
-            });
-            for (var _i = 0, _a = this.getTile(hash); _i < _a.length; _i++) {
-                var node = _a[_i];
-                if (reconstructionKeys.indexOf(node.key) === -1) {
-                    tile.push(node);
+        var clusterKeys = this.getTile(hash)
+            .filter(function (nd) {
+            return !!nd.clusterKey;
+        })
+            .map(function (nd) {
+            return nd.clusterKey;
+        })
+            .filter(function (v, i, a) {
+            return a.indexOf(v) === i;
+        });
+        this._tileClusters[hash] = clusterKeys;
+        this._cacheRequests[hash] = [];
+        this._cachingClusterReconstructions$[hash] = rxjs_1.from(clusterKeys).pipe(operators_1.mergeMap(function (key) {
+            if (_this._hasClusterReconstruction(key)) {
+                return rxjs_1.of(_this._getClusterReconstruction(key));
+            }
+            return _this._getClusterReconstruction$(key, _this._cacheRequests[hash])
+                .pipe(operators_1.catchError(function (error) {
+                if (error instanceof Error_1.AbortMapillaryError) {
+                    return rxjs_1.empty();
                 }
+                console.error(error);
+                return rxjs_1.empty();
+            }));
+        }, 6), operators_1.filter(function () {
+            return hash in _this._tileClusters;
+        }), operators_1.tap(function (reconstruction) {
+            if (!_this._hasClusterReconstruction(reconstruction.key)) {
+                _this._clusterReconstructions[reconstruction.key] = reconstruction;
+            }
+            if (!(reconstruction.key in _this._clusterReconstructionTiles)) {
+                _this._clusterReconstructionTiles[reconstruction.key] = [];
+            }
+            if (_this._clusterReconstructionTiles[reconstruction.key].indexOf(hash) === -1) {
+                _this._clusterReconstructionTiles[reconstruction.key].push(hash);
             }
-        }
-        else {
-            tile.push.apply(tile, this.getTile(hash));
-            this._reconstructions[hash] = [];
-        }
-        this._cacheRequests[hash] = [];
-        this._cachingReconstructions$[hash] = rxjs_1.from(tile).pipe(operators_1.mergeMap(function (nodeData) {
-            return !_this._cacheRequests[hash] ?
-                rxjs_1.empty() :
-                rxjs_1.zip(rxjs_1.of(nodeData), _this._getAtomicReconstruction(nodeData.key, _this._cacheRequests[hash]))
-                    .pipe(operators_1.catchError(function (error) {
-                    if (error instanceof Error_1.AbortMapillaryError) {
-                        return rxjs_1.empty();
-                    }
-                    console.error(error);
-                    return rxjs_1.of([nodeData, null]);
-                }));
-        }, 6), operators_1.map(function (_a) {
-            var nodeData = _a[0], reconstruction = _a[1];
-            return { data: nodeData, reconstruction: reconstruction };
-        }), operators_1.filter(function () {
-            return hash in _this._reconstructions;
-        }), operators_1.tap(function (data) {
-            _this._reconstructions[hash].push(data);
-        }), operators_1.filter(function (data) {
-            return !!data.reconstruction;
         }), operators_1.finalize(function () {
-            if (hash in _this._cachingReconstructions$) {
-                delete _this._cachingReconstructions$[hash];
+            if (hash in _this._cachingClusterReconstructions$) {
+                delete _this._cachingClusterReconstructions$[hash];
             }
             if (hash in _this._cacheRequests) {
                 delete _this._cacheRequests[hash];
             }
         }), operators_1.publish(), operators_1.refCount());
-        return this._cachingReconstructions$[hash];
+        return this._cachingClusterReconstructions$[hash];
     };
     SpatialDataCache.prototype.cacheTile$ = function (hash) {
         var _this = this;
@@ -30673,16 +37956,14 @@ var SpatialDataCache = /** @class */ (function () {
         if (this.hasTile(hash)) {
             throw new Error("Cannot cache tile that already exists.");
         }
-        if (this.hasTile(hash)) {
+        if (this.isCachingTile(hash)) {
             return this._cachingTiles$[hash];
         }
         var bounds = geohash.bounds(hash);
         var sw = { lat: bounds.sw.lat, lon: bounds.sw.lon };
         var ne = { lat: bounds.ne.lat, lon: bounds.ne.lon };
-        this._tiles[hash] = [];
         this._cachingTiles$[hash] = this._graphService.cacheBoundingBox$(sw, ne).pipe(operators_1.catchError(function (error) {
             console.error(error);
-            delete _this._tiles[hash];
             return rxjs_1.empty();
         }), operators_1.map(function (nodes) {
             return nodes
@@ -30690,9 +37971,10 @@ var SpatialDataCache = /** @class */ (function () {
                 return _this._createNodeData(n);
             });
         }), operators_1.filter(function () {
-            return hash in _this._tiles;
+            return !(hash in _this._tiles);
         }), operators_1.tap(function (nodeData) {
             var _a;
+            _this._tiles[hash] = [];
             (_a = _this._tiles[hash]).push.apply(_a, nodeData);
             delete _this._cachingTiles$[hash];
         }), operators_1.finalize(function () {
@@ -30702,25 +37984,37 @@ var SpatialDataCache = /** @class */ (function () {
         }), operators_1.publish(), operators_1.refCount());
         return this._cachingTiles$[hash];
     };
-    SpatialDataCache.prototype.isCachingReconstructions = function (hash) {
-        return hash in this._cachingReconstructions$;
+    SpatialDataCache.prototype.isCachingClusterReconstructions = function (hash) {
+        return hash in this._cachingClusterReconstructions$;
     };
     SpatialDataCache.prototype.isCachingTile = function (hash) {
         return hash in this._cachingTiles$;
     };
-    SpatialDataCache.prototype.hasReconstructions = function (hash) {
-        return !(hash in this._cachingReconstructions$) &&
-            hash in this._reconstructions &&
-            this._reconstructions[hash].length === this._tiles[hash].length;
+    SpatialDataCache.prototype.hasClusterReconstructions = function (hash) {
+        if (hash in this._cachingClusterReconstructions$ ||
+            !(hash in this._tileClusters)) {
+            return false;
+        }
+        for (var _i = 0, _a = this._tileClusters[hash]; _i < _a.length; _i++) {
+            var key = _a[_i];
+            if (!(key in this._clusterReconstructions)) {
+                return false;
+            }
+        }
+        return true;
     };
     SpatialDataCache.prototype.hasTile = function (hash) {
         return !(hash in this._cachingTiles$) && hash in this._tiles;
     };
-    SpatialDataCache.prototype.getReconstructions = function (hash) {
-        return hash in this._reconstructions ?
-            this._reconstructions[hash]
-                .filter(function (data) {
-                return !!data.reconstruction;
+    SpatialDataCache.prototype.getClusterReconstructions = function (hash) {
+        var _this = this;
+        return hash in this._tileClusters ?
+            this._tileClusters[hash]
+                .map(function (key) {
+                return _this._clusterReconstructions[key];
+            })
+                .filter(function (reconstruction) {
+                return !!reconstruction;
             }) :
             [];
     };
@@ -30739,15 +38033,31 @@ var SpatialDataCache = /** @class */ (function () {
             }
             delete this._cacheRequests[hash];
         }
-        for (var _d = 0, _e = Object.keys(this._reconstructions); _d < _e.length; _d++) {
+        for (var _d = 0, _e = Object.keys(this._tileClusters); _d < _e.length; _d++) {
             var hash = _e[_d];
             if (!!keepHashes && keepHashes.indexOf(hash) !== -1) {
                 continue;
             }
-            delete this._reconstructions[hash];
+            for (var _f = 0, _g = this._tileClusters[hash]; _f < _g.length; _f++) {
+                var key = _g[_f];
+                if (!(key in this._clusterReconstructionTiles)) {
+                    continue;
+                }
+                var index = this._clusterReconstructionTiles[key].indexOf(hash);
+                if (index === -1) {
+                    continue;
+                }
+                this._clusterReconstructionTiles[key].splice(index, 1);
+                if (this._clusterReconstructionTiles[key].length > 0) {
+                    continue;
+                }
+                delete this._clusterReconstructionTiles[key];
+                delete this._clusterReconstructions[key];
+            }
+            delete this._tileClusters[hash];
         }
-        for (var _f = 0, _g = Object.keys(this._tiles); _f < _g.length; _f++) {
-            var hash = _g[_f];
+        for (var _h = 0, _j = Object.keys(this._tiles); _h < _j.length; _h++) {
+            var hash = _j[_h];
             if (!!keepHashes && keepHashes.indexOf(hash) !== -1) {
                 continue;
             }
@@ -30758,6 +38068,7 @@ var SpatialDataCache = /** @class */ (function () {
         return {
             alt: node.alt,
             cameraProjection: node.cameraProjection,
+            clusterKey: node.clusterKey,
             focal: node.focal,
             gpano: node.gpano,
             height: node.height,
@@ -30772,43 +38083,57 @@ var SpatialDataCache = /** @class */ (function () {
             originalLon: node.originalLatLon.lon,
             rotation: [node.rotation[0], node.rotation[1], node.rotation[2]],
             scale: node.scale,
+            sequenceKey: node.sequenceKey,
             width: node.width,
         };
     };
-    SpatialDataCache.prototype._getAtomicReconstruction = function (key, requests) {
+    SpatialDataCache.prototype._getClusterReconstruction = function (key) {
+        return this._clusterReconstructions[key];
+    };
+    SpatialDataCache.prototype._getClusterReconstruction$ = function (key, requests) {
         return rxjs_1.Observable.create(function (subscriber) {
-            var xmlHTTP = new XMLHttpRequest();
-            xmlHTTP.open("GET", Utils_1.Urls.atomicReconstruction(key), true);
-            xmlHTTP.responseType = "json";
-            xmlHTTP.timeout = 15000;
-            xmlHTTP.onload = function () {
-                if (!xmlHTTP.response) {
-                    subscriber.error(new Error("Atomic reconstruction does not exist (" + key + ")"));
+            var xhr = new XMLHttpRequest();
+            xhr.open("GET", Utils_1.Urls.clusterReconstruction(key), true);
+            xhr.responseType = "arraybuffer";
+            xhr.timeout = 15000;
+            xhr.onload = function () {
+                if (!xhr.response) {
+                    subscriber.error(new Error("Cluster reconstruction retreival failed (" + key + ")"));
                 }
                 else {
-                    subscriber.next(xmlHTTP.response);
+                    var inflated = pako.inflate(xhr.response, { to: "string" });
+                    var reconstructions = JSON.parse(inflated);
+                    if (reconstructions.length < 1) {
+                        subscriber.error(new Error("No cluster reconstruction exists (" + key + ")"));
+                    }
+                    var reconstruction = reconstructions[0];
+                    reconstruction.key = key;
+                    subscriber.next(reconstruction);
                     subscriber.complete();
                 }
             };
-            xmlHTTP.onerror = function () {
-                subscriber.error(new Error("Failed to get atomic reconstruction (" + key + ")"));
+            xhr.onerror = function () {
+                subscriber.error(new Error("Failed to get cluster reconstruction (" + key + ")"));
             };
-            xmlHTTP.ontimeout = function () {
-                subscriber.error(new Error("Atomic reconstruction request timed out (" + key + ")"));
+            xhr.ontimeout = function () {
+                subscriber.error(new Error("Cluster reconstruction request timed out (" + key + ")"));
             };
-            xmlHTTP.onabort = function () {
-                subscriber.error(new Error_1.AbortMapillaryError("Atomic reconstruction request was aborted (" + key + ")"));
+            xhr.onabort = function () {
+                subscriber.error(new Error_1.AbortMapillaryError("Cluster reconstruction request was aborted (" + key + ")"));
             };
-            requests.push(xmlHTTP);
-            xmlHTTP.send(null);
+            requests.push(xhr);
+            xhr.send(null);
         });
     };
+    SpatialDataCache.prototype._hasClusterReconstruction = function (key) {
+        return key in this._clusterReconstructions;
+    };
     return SpatialDataCache;
 }());
 exports.SpatialDataCache = SpatialDataCache;
 exports.default = SpatialDataCache;
 
-},{"../../Error":277,"../../Utils":285,"latlon-geohash":21,"rxjs":27,"rxjs/operators":225}],341:[function(require,module,exports){
+},{"../../Error":293,"../../Utils":301,"latlon-geohash":21,"pako":23,"rxjs":43,"rxjs/operators":241}],359:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -30832,6 +38157,7 @@ var Geo_1 = require("../../Geo");
 var Render_1 = require("../../Render");
 var PlayService_1 = require("../../viewer/PlayService");
 var State_1 = require("../../state/State");
+var CameraVisualizationMode_1 = require("./CameraVisualizationMode");
 var SpatialDataComponent = /** @class */ (function (_super) {
     __extends(SpatialDataComponent, _super);
     function SpatialDataComponent(name, container, navigator) {
@@ -30883,7 +38209,7 @@ var SpatialDataComponent = /** @class */ (function (_super) {
             var playing = _a[0], speed = _a[1];
             return playing && speed > PlayService_1.default.sequenceSpeed;
         }), operators_1.distinctUntilChanged(), operators_1.publishReplay(1), operators_1.refCount());
-        this._addSubscription = rxjs_1.combineLatest(this._navigator.stateService.state$.pipe(operators_1.map(function (state) {
+        var hashes$ = rxjs_1.combineLatest(this._navigator.stateService.state$.pipe(operators_1.map(function (state) {
             return state === State_1.default.Earth;
         }), operators_1.distinctUntilChanged()), hash$, sequencePlay$, direction$).pipe(operators_1.distinctUntilChanged(function (_a, _b) {
             var e1 = _a[0], h1 = _a[1], s1 = _a[2], d1 = _a[3];
@@ -30905,63 +38231,59 @@ var SpatialDataComponent = /** @class */ (function (_super) {
             return sequencePlay ?
                 rxjs_1.of([hash, geohash.neighbours(hash)[direction]]) :
                 rxjs_1.of(_this._computeTiles(hash, direction));
-        }), operators_1.switchMap(function (hashes) {
+        }), operators_1.publish(), operators_1.refCount());
+        var tile$ = hashes$.pipe(operators_1.switchMap(function (hashes) {
             return rxjs_1.from(hashes).pipe(operators_1.mergeMap(function (h) {
-                var tile$;
-                if (_this._cache.hasTile(h)) {
-                    tile$ = rxjs_1.of(_this._cache.getTile(h));
-                }
-                else if (_this._cache.isCachingTile(h)) {
-                    tile$ = _this._cache.cacheTile$(h).pipe(operators_1.last(null, {}), operators_1.switchMap(function () {
-                        return rxjs_1.of(_this._cache.getTile(h));
-                    }));
-                }
-                else {
-                    tile$ = _this._cache.cacheTile$(h);
+                var t$ = _this._cache.hasTile(h) ?
+                    rxjs_1.of(_this._cache.getTile(h)) :
+                    _this._cache.cacheTile$(h);
+                return rxjs_1.combineLatest(rxjs_1.of(h), t$);
+            }, 6));
+        }), operators_1.publish(), operators_1.refCount());
+        this._addTileSubscription = tile$.pipe(operators_1.withLatestFrom(this._navigator.stateService.reference$))
+            .subscribe(function (_a) {
+            var hash = _a[0][0], reference = _a[1];
+            if (_this._scene.hasTile(hash)) {
+                return;
+            }
+            _this._scene.addTile(_this._computeTileBBox(hash, reference), hash);
+        });
+        this._addNodeSubscription = tile$.pipe(operators_1.withLatestFrom(this._navigator.stateService.reference$))
+            .subscribe(function (_a) {
+            var _b = _a[0], hash = _b[0], datas = _b[1], reference = _a[1];
+            for (var _i = 0, datas_1 = datas; _i < datas_1.length; _i++) {
+                var data = datas_1[_i];
+                if (_this._scene.hasNode(data.key, hash)) {
+                    continue;
                 }
-                return rxjs_1.combineLatest(rxjs_1.of(h), tile$);
-            }, 1), operators_1.map(function (_a) {
-                var hash = _a[0];
-                return hash;
-            }));
-        }), operators_1.concatMap(function (hash) {
+                _this._scene.addNode(data, _this._createTransform(data, reference), _this._computeOriginalPosition(data, reference), hash);
+            }
+        });
+        this._addReconstructionSubscription = tile$.pipe(operators_1.concatMap(function (_a) {
+            var hash = _a[0];
             var reconstructions$;
-            if (_this._cache.hasReconstructions(hash)) {
-                reconstructions$ = rxjs_1.from(_this._cache.getReconstructions(hash));
+            if (_this._cache.hasClusterReconstructions(hash)) {
+                reconstructions$ = rxjs_1.from(_this._cache.getClusterReconstructions(hash));
             }
-            else if (_this._cache.isCachingReconstructions(hash)) {
-                reconstructions$ = _this._cache.cacheReconstructions$(hash).pipe(operators_1.last(null, {}), operators_1.switchMap(function () {
-                    return rxjs_1.from(_this._cache.getReconstructions(hash));
+            else if (_this._cache.isCachingClusterReconstructions(hash)) {
+                reconstructions$ = _this._cache.cacheClusterReconstructions$(hash).pipe(operators_1.last(null, {}), operators_1.switchMap(function () {
+                    return rxjs_1.from(_this._cache.getClusterReconstructions(hash));
                 }));
             }
             else if (_this._cache.hasTile(hash)) {
-                reconstructions$ = _this._cache.cacheReconstructions$(hash);
+                reconstructions$ = _this._cache.cacheClusterReconstructions$(hash);
             }
             else {
                 reconstructions$ = rxjs_1.empty();
             }
             return rxjs_1.combineLatest(rxjs_1.of(hash), reconstructions$);
-        }), operators_1.withLatestFrom(this._navigator.stateService.reference$), operators_1.tap(function (_a) {
-            var hash = _a[0][0], reference = _a[1];
-            if (_this._scene.hasTile(hash)) {
+        }), operators_1.withLatestFrom(this._navigator.stateService.reference$))
+            .subscribe(function (_a) {
+            var _b = _a[0], hash = _b[0], reconstruction = _b[1], reference = _a[1];
+            if (_this._scene.hasClusterReconstruction(reconstruction.key, hash)) {
                 return;
             }
-            _this._scene.addTile(_this._computeTileBBox(hash, reference), hash);
-        }), operators_1.filter(function (_a) {
-            var _b = _a[0], hash = _b[0], data = _b[1];
-            return !_this._scene.hasReconstruction(data.reconstruction.main_shot, hash);
-        }), operators_1.map(function (_a) {
-            var _b = _a[0], hash = _b[0], data = _b[1], reference = _a[1];
-            return [
-                data,
-                _this._createTransform(data.data, reference),
-                _this._computeOriginalPosition(data.data, reference),
-                hash
-            ];
-        }))
-            .subscribe(function (_a) {
-            var data = _a[0], transform = _a[1], position = _a[2], hash = _a[3];
-            _this._scene.addReconstruction(data.reconstruction, transform, position, !!data.data.mergeCC ? data.data.mergeCC.toString() : "", hash);
+            _this._scene.addClusterReconstruction(reconstruction, _this._computeTranslation(reconstruction, reference), hash);
         });
         this._cameraVisibilitySubscription = this._configuration$.pipe(operators_1.map(function (configuration) {
             return configuration.camerasVisible;
@@ -30987,11 +38309,19 @@ var SpatialDataComponent = /** @class */ (function (_super) {
             .subscribe(function (visible) {
             _this._scene.setTileVisibility(visible);
         });
-        this._visualizeConnectedComponentSubscription = this._configuration$.pipe(operators_1.map(function (configuration) {
-            return configuration.connectedComponents;
+        this._ccToModeSubscription = this._configuration$.pipe(operators_1.map(function (configuration) {
+            return configuration.connectedComponents === true ?
+                CameraVisualizationMode_1.default.ConnectedComponent :
+                CameraVisualizationMode_1.default.Default;
         }), operators_1.distinctUntilChanged())
-            .subscribe(function (visualize) {
-            _this._scene.setConnectedComponentVisualization(visualize);
+            .subscribe(function (mode) {
+            _this.configure({ cameraVisualizationMode: mode });
+        });
+        this._cameraVisualizationModeSubscription = this._configuration$.pipe(operators_1.map(function (configuration) {
+            return configuration.cameraVisualizationMode;
+        }), operators_1.distinctUntilChanged())
+            .subscribe(function (mode) {
+            _this._scene.setCameraVisualizationMode(mode);
         });
         this._uncacheSubscription = hash$
             .subscribe(function (hash) {
@@ -31034,7 +38364,9 @@ var SpatialDataComponent = /** @class */ (function (_super) {
         var _this = this;
         this._cache.uncache();
         this._scene.uncache();
-        this._addSubscription.unsubscribe();
+        this._addNodeSubscription.unsubscribe();
+        this._addReconstructionSubscription.unsubscribe();
+        this._addTileSubscription.unsubscribe();
         this._cameraVisibilitySubscription.unsubscribe();
         this._earthControlsSubscription.unsubscribe();
         this._moveSubscription.unsubscribe();
@@ -31043,7 +38375,8 @@ var SpatialDataComponent = /** @class */ (function (_super) {
         this._renderSubscription.unsubscribe();
         this._tileVisibilitySubscription.unsubscribe();
         this._uncacheSubscription.unsubscribe();
-        this._visualizeConnectedComponentSubscription.unsubscribe();
+        this._cameraVisualizationModeSubscription.unsubscribe();
+        this._ccToModeSubscription.unsubscribe();
         this._navigator.stateService.state$.pipe(operators_1.first())
             .subscribe(function (state) {
             if (state === State_1.default.Earth) {
@@ -31052,7 +38385,14 @@ var SpatialDataComponent = /** @class */ (function (_super) {
         });
     };
     SpatialDataComponent.prototype._getDefaultConfiguration = function () {
-        return { camerasVisible: false, pointsVisible: true, positionsVisible: false, tilesVisible: false };
+        return {
+            cameraVisualizationMode: CameraVisualizationMode_1.default.Default,
+            camerasVisible: false,
+            connectedComponents: false,
+            pointsVisible: true,
+            positionsVisible: false,
+            tilesVisible: false,
+        };
     };
     SpatialDataComponent.prototype._adjacentComponent = function (hash, depth) {
         var hashSet = new Set();
@@ -31123,6 +38463,9 @@ var SpatialDataComponent = /** @class */ (function (_super) {
             this._computeTilesRecursive(hashSet, directionNeighbour, direction, directions, currentDepth + 1, maxDepth);
         }
     };
+    SpatialDataComponent.prototype._computeTranslation = function (reconstruction, reference) {
+        return this._geoCoords.geodeticToEnu(reconstruction.reference_lla.latitude, reconstruction.reference_lla.longitude, reconstruction.reference_lla.altitude, reference.lat, reference.lon, reference.alt);
+    };
     SpatialDataComponent.prototype._modulo = function (a, n) {
         return ((a % n) + n) % n;
     };
@@ -31140,24 +38483,33 @@ exports.SpatialDataComponent = SpatialDataComponent;
 Component_1.ComponentService.register(SpatialDataComponent);
 exports.default = SpatialDataComponent;
 
-},{"../../Component":275,"../../Geo":278,"../../Render":281,"../../state/State":412,"../../viewer/PlayService":441,"latlon-geohash":21,"rxjs":27,"rxjs/operators":225}],342:[function(require,module,exports){
+},{"../../Component":291,"../../Geo":294,"../../Render":297,"../../state/State":438,"../../viewer/PlayService":468,"./CameraVisualizationMode":356,"latlon-geohash":21,"rxjs":43,"rxjs/operators":241}],360:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
+var CameraVisualizationMode_1 = require("./CameraVisualizationMode");
 var SpatialDataScene = /** @class */ (function () {
     function SpatialDataScene(configuration, scene, raycaster) {
         this._scene = !!scene ? scene : new THREE.Scene();
         this._raycaster = !!raycaster ? raycaster : new THREE.Raycaster(undefined, undefined, 0.8);
-        this._connectedComponentColors = {};
+        this._cameraColors = {};
         this._needsRender = false;
         this._interactiveObjects = [];
-        this._reconstructions = {};
+        this._nodes = {};
         this._tiles = {};
+        this._tileClusterReconstructions = {};
+        this._clusterReconstructions = {};
+        this._cameraVisualizationMode = !!configuration.cameraVisualizationMode ?
+            configuration.cameraVisualizationMode :
+            CameraVisualizationMode_1.default.Default;
+        if (this._cameraVisualizationMode === CameraVisualizationMode_1.default.Default &&
+            configuration.connectedComponents === true) {
+            this._cameraVisualizationMode = CameraVisualizationMode_1.default.ConnectedComponent;
+        }
         this._camerasVisible = configuration.camerasVisible;
         this._pointsVisible = configuration.pointsVisible;
         this._positionsVisible = configuration.positionsVisible;
         this._tilesVisible = configuration.tilesVisible;
-        this._visualizeConnectedComponents = configuration.connectedComponents;
     }
     Object.defineProperty(SpatialDataScene.prototype, "needsRender", {
         get: function () {
@@ -31166,39 +38518,79 @@ var SpatialDataScene = /** @class */ (function () {
         enumerable: true,
         configurable: true
     });
-    SpatialDataScene.prototype.addReconstruction = function (reconstruction, transform, originalPosition, connectedComponent, hash) {
-        if (!(hash in this._reconstructions)) {
-            this._reconstructions[hash] = {
+    SpatialDataScene.prototype.addClusterReconstruction = function (reconstruction, translation, hash) {
+        if (this.hasClusterReconstruction(reconstruction.key, hash)) {
+            return;
+        }
+        var key = reconstruction.key;
+        if (!(key in this._clusterReconstructions)) {
+            this._clusterReconstructions[key] = {
+                points: new THREE.Object3D(),
+                tiles: [],
+            };
+            this._clusterReconstructions[key].points.visible = this._pointsVisible;
+            this._clusterReconstructions[key].points.add(this._createClusterPoints(reconstruction, translation));
+            this._scene.add(this._clusterReconstructions[key].points);
+        }
+        if (this._clusterReconstructions[key].tiles.indexOf(hash) === -1) {
+            this._clusterReconstructions[key].tiles.push(hash);
+        }
+        if (!(hash in this._tileClusterReconstructions)) {
+            this._tileClusterReconstructions[hash] = {
+                keys: [],
+            };
+        }
+        if (this._tileClusterReconstructions[hash].keys.indexOf(key) === -1) {
+            this._tileClusterReconstructions[hash].keys.push(key);
+        }
+        this._needsRender = true;
+    };
+    SpatialDataScene.prototype.addNode = function (data, transform, originalPosition, hash) {
+        var key = data.key;
+        var clusterKey = data.clusterKey;
+        var sequenceKey = data.sequenceKey;
+        var connectedComponent = !!data.mergeCC ? data.mergeCC.toString() : "";
+        if (this.hasNode(key, hash)) {
+            return;
+        }
+        if (!(hash in this._nodes)) {
+            this._nodes[hash] = {
                 cameraKeys: {},
                 cameras: new THREE.Object3D(),
+                clusters: {},
                 connectedComponents: {},
                 keys: [],
-                points: new THREE.Object3D(),
                 positions: new THREE.Object3D(),
+                sequences: {},
             };
-            this._reconstructions[hash].cameras.visible = this._camerasVisible;
-            this._reconstructions[hash].points.visible = this._pointsVisible;
-            this._reconstructions[hash].positions.visible = this._positionsVisible;
-            this._scene.add(this._reconstructions[hash].cameras, this._reconstructions[hash].points, this._reconstructions[hash].positions);
+            this._nodes[hash].cameras.visible = this._camerasVisible;
+            this._nodes[hash].positions.visible = this._positionsVisible;
+            this._scene.add(this._nodes[hash].cameras, this._nodes[hash].positions);
+        }
+        if (!(connectedComponent in this._nodes[hash].connectedComponents)) {
+            this._nodes[hash].connectedComponents[connectedComponent] = [];
         }
-        if (!(connectedComponent in this._reconstructions[hash].connectedComponents)) {
-            this._reconstructions[hash].connectedComponents[connectedComponent] = [];
+        if (!(clusterKey in this._nodes[hash].clusters)) {
+            this._nodes[hash].clusters[clusterKey] = [];
         }
-        if (transform.hasValidScale) {
-            this._reconstructions[hash].points.add(this._createPoints(reconstruction, transform));
+        if (!(sequenceKey in this._nodes[hash].sequences)) {
+            this._nodes[hash].sequences[sequenceKey] = [];
         }
         var camera = this._createCamera(transform);
-        this._reconstructions[hash].cameras.add(camera);
+        this._nodes[hash].cameras.add(camera);
         for (var _i = 0, _a = camera.children; _i < _a.length; _i++) {
             var child = _a[_i];
-            this._reconstructions[hash].cameraKeys[child.uuid] = reconstruction.main_shot;
+            this._nodes[hash].cameraKeys[child.uuid] = key;
             this._interactiveObjects.push(child);
         }
-        this._reconstructions[hash].connectedComponents[connectedComponent].push(camera);
-        var color = this._getColor(connectedComponent, this._visualizeConnectedComponents);
+        this._nodes[hash].connectedComponents[connectedComponent].push(camera);
+        this._nodes[hash].clusters[clusterKey].push(camera);
+        this._nodes[hash].sequences[sequenceKey].push(camera);
+        var id = this._getId(clusterKey, connectedComponent, sequenceKey, this._cameraVisualizationMode);
+        var color = this._getColor(id, this._cameraVisualizationMode);
         this._setCameraColor(color, camera);
-        this._reconstructions[hash].positions.add(this._createPosition(transform, originalPosition));
-        this._reconstructions[hash].keys.push(reconstruction.main_shot);
+        this._nodes[hash].positions.add(this._createPosition(transform, originalPosition));
+        this._nodes[hash].keys.push(key);
         this._needsRender = true;
     };
     SpatialDataScene.prototype.addTile = function (tileBBox, hash) {
@@ -31217,28 +38609,39 @@ var SpatialDataScene = /** @class */ (function () {
         this._needsRender = true;
     };
     SpatialDataScene.prototype.uncache = function (keepHashes) {
-        for (var _i = 0, _a = Object.keys(this._reconstructions); _i < _a.length; _i++) {
+        for (var _i = 0, _a = Object.keys(this._tileClusterReconstructions); _i < _a.length; _i++) {
             var hash = _a[_i];
             if (!!keepHashes && keepHashes.indexOf(hash) !== -1) {
                 continue;
             }
             this._disposeReconstruction(hash);
         }
-        for (var _b = 0, _c = Object.keys(this._tiles); _b < _c.length; _b++) {
+        for (var _b = 0, _c = Object.keys(this._nodes); _b < _c.length; _b++) {
             var hash = _c[_b];
             if (!!keepHashes && keepHashes.indexOf(hash) !== -1) {
                 continue;
             }
+            this._disposeNodes(hash);
+        }
+        for (var _d = 0, _e = Object.keys(this._tiles); _d < _e.length; _d++) {
+            var hash = _e[_d];
+            if (!!keepHashes && keepHashes.indexOf(hash) !== -1) {
+                continue;
+            }
             this._disposeTile(hash);
         }
         this._needsRender = true;
     };
-    SpatialDataScene.prototype.hasReconstruction = function (key, hash) {
-        return hash in this._reconstructions && this._reconstructions[hash].keys.indexOf(key) !== -1;
+    SpatialDataScene.prototype.hasClusterReconstruction = function (key, hash) {
+        return key in this._clusterReconstructions &&
+            this._clusterReconstructions[key].tiles.indexOf(hash) !== -1;
     };
     SpatialDataScene.prototype.hasTile = function (hash) {
         return hash in this._tiles;
     };
+    SpatialDataScene.prototype.hasNode = function (key, hash) {
+        return hash in this._nodes && this._nodes[hash].keys.indexOf(key) !== -1;
+    };
     SpatialDataScene.prototype.intersectObjects = function (_a, camera) {
         var viewportX = _a[0], viewportY = _a[1];
         if (!this._camerasVisible) {
@@ -31248,12 +38651,12 @@ var SpatialDataScene = /** @class */ (function () {
         var intersects = this._raycaster.intersectObjects(this._interactiveObjects);
         for (var _i = 0, intersects_1 = intersects; _i < intersects_1.length; _i++) {
             var intersect = intersects_1[_i];
-            for (var hash in this._reconstructions) {
-                if (!this._reconstructions.hasOwnProperty(hash)) {
+            for (var hash in this._nodes) {
+                if (!this._nodes.hasOwnProperty(hash)) {
                     continue;
                 }
-                if (intersect.object.uuid in this._reconstructions[hash].cameraKeys) {
-                    return this._reconstructions[hash].cameraKeys[intersect.object.uuid];
+                if (intersect.object.uuid in this._nodes[hash].cameraKeys) {
+                    return this._nodes[hash].cameraKeys[intersect.object.uuid];
                 }
             }
         }
@@ -31263,11 +38666,11 @@ var SpatialDataScene = /** @class */ (function () {
         if (visible === this._camerasVisible) {
             return;
         }
-        for (var hash in this._reconstructions) {
-            if (!this._reconstructions.hasOwnProperty(hash)) {
+        for (var hash in this._nodes) {
+            if (!this._nodes.hasOwnProperty(hash)) {
                 continue;
             }
-            this._reconstructions[hash].cameras.visible = visible;
+            this._nodes[hash].cameras.visible = visible;
         }
         this._camerasVisible = visible;
         this._needsRender = true;
@@ -31276,11 +38679,11 @@ var SpatialDataScene = /** @class */ (function () {
         if (visible === this._pointsVisible) {
             return;
         }
-        for (var hash in this._reconstructions) {
-            if (!this._reconstructions.hasOwnProperty(hash)) {
+        for (var key in this._clusterReconstructions) {
+            if (!this._clusterReconstructions.hasOwnProperty(key)) {
                 continue;
             }
-            this._reconstructions[hash].points.visible = visible;
+            this._clusterReconstructions[key].points.visible = visible;
         }
         this._pointsVisible = visible;
         this._needsRender = true;
@@ -31289,11 +38692,11 @@ var SpatialDataScene = /** @class */ (function () {
         if (visible === this._positionsVisible) {
             return;
         }
-        for (var hash in this._reconstructions) {
-            if (!this._reconstructions.hasOwnProperty(hash)) {
+        for (var hash in this._nodes) {
+            if (!this._nodes.hasOwnProperty(hash)) {
                 continue;
             }
-            this._reconstructions[hash].positions.visible = visible;
+            this._nodes[hash].positions.visible = visible;
         }
         this._positionsVisible = visible;
         this._needsRender = true;
@@ -31311,27 +38714,44 @@ var SpatialDataScene = /** @class */ (function () {
         this._tilesVisible = visible;
         this._needsRender = true;
     };
-    SpatialDataScene.prototype.setConnectedComponentVisualization = function (visualize) {
-        if (visualize === this._visualizeConnectedComponents) {
+    SpatialDataScene.prototype.setCameraVisualizationMode = function (mode) {
+        if (mode === this._cameraVisualizationMode) {
             return;
         }
-        for (var hash in this._reconstructions) {
-            if (!this._reconstructions.hasOwnProperty(hash)) {
+        for (var hash in this._nodes) {
+            if (!this._nodes.hasOwnProperty(hash)) {
                 continue;
             }
-            var connectedComponents = this._reconstructions[hash].connectedComponents;
-            for (var connectedComponent in connectedComponents) {
-                if (!connectedComponents.hasOwnProperty(connectedComponent)) {
+            var cameras = undefined;
+            if (mode === CameraVisualizationMode_1.default.Cluster) {
+                cameras = this._nodes[hash].clusters;
+            }
+            else if (mode === CameraVisualizationMode_1.default.ConnectedComponent) {
+                cameras = this._nodes[hash].connectedComponents;
+            }
+            else if (mode === CameraVisualizationMode_1.default.Sequence) {
+                cameras = this._nodes[hash].sequences;
+            }
+            else {
+                for (var _i = 0, _a = this._nodes[hash].cameras.children; _i < _a.length; _i++) {
+                    var child = _a[_i];
+                    var color = this._getColor("", mode);
+                    this._setCameraColor(color, child);
+                }
+                continue;
+            }
+            for (var id in cameras) {
+                if (!cameras.hasOwnProperty(id)) {
                     continue;
                 }
-                var color = this._getColor(connectedComponent, visualize);
-                for (var _i = 0, _a = connectedComponents[connectedComponent]; _i < _a.length; _i++) {
-                    var camera = _a[_i];
+                var color = this._getColor(id, mode);
+                for (var _b = 0, _c = cameras[id]; _b < _c.length; _b++) {
+                    var camera = _c[_b];
                     this._setCameraColor(color, camera);
                 }
             }
         }
-        this._visualizeConnectedComponents = visualize;
+        this._cameraVisualizationMode = mode;
         this._needsRender = true;
     };
     SpatialDataScene.prototype.render = function (perspectiveCamera, renderer) {
@@ -31427,8 +38847,7 @@ var SpatialDataScene = /** @class */ (function () {
         camera.children.push(this._createLongitude(0.75, 6, transform));
         return camera;
     };
-    SpatialDataScene.prototype._createPoints = function (reconstruction, transform) {
-        var srtInverse = new THREE.Matrix4().getInverse(transform.srt);
+    SpatialDataScene.prototype._createClusterPoints = function (reconstruction, translation) {
         var points = Object
             .keys(reconstruction.points)
             .map(function (key) {
@@ -31441,7 +38860,7 @@ var SpatialDataScene = /** @class */ (function () {
             var index = 3 * i;
             var coords = points[i].coordinates;
             var point = new THREE.Vector3(coords[0], coords[1], coords[2])
-                .applyMatrix4(srtInverse);
+                .add(new THREE.Vector3().fromArray(translation));
             positions[index + 0] = point.x;
             positions[index + 1] = point.y;
             positions[index + 2] = point.z;
@@ -31474,7 +38893,7 @@ var SpatialDataScene = /** @class */ (function () {
         return camera;
     };
     SpatialDataScene.prototype._disposeCameras = function (hash) {
-        var tileCameras = this._reconstructions[hash].cameras;
+        var tileCameras = this._nodes[hash].cameras;
         for (var _i = 0, _a = tileCameras.children.slice(); _i < _a.length; _i++) {
             var camera = _a[_i];
             for (var _b = 0, _c = camera.children; _b < _c.length; _b++) {
@@ -31494,17 +38913,30 @@ var SpatialDataScene = /** @class */ (function () {
         this._scene.remove(tileCameras);
     };
     SpatialDataScene.prototype._disposePoints = function (hash) {
-        var tilePoints = this._reconstructions[hash].points;
-        for (var _i = 0, _a = tilePoints.children.slice(); _i < _a.length; _i++) {
-            var points = _a[_i];
-            points.geometry.dispose();
-            points.material.dispose();
-            tilePoints.remove(points);
+        for (var _i = 0, _a = this._tileClusterReconstructions[hash].keys; _i < _a.length; _i++) {
+            var key = _a[_i];
+            if (!(key in this._clusterReconstructions)) {
+                continue;
+            }
+            var index = this._clusterReconstructions[key].tiles.indexOf(hash);
+            if (index === -1) {
+                continue;
+            }
+            this._clusterReconstructions[key].tiles.splice(index, 1);
+            if (this._clusterReconstructions[key].tiles.length > 0) {
+                continue;
+            }
+            for (var _b = 0, _c = this._clusterReconstructions[key].points.children.slice(); _b < _c.length; _b++) {
+                var points = _c[_b];
+                points.geometry.dispose();
+                points.material.dispose();
+            }
+            this._scene.remove(this._clusterReconstructions[key].points);
+            delete this._clusterReconstructions[key];
         }
-        this._scene.remove(tilePoints);
     };
     SpatialDataScene.prototype._disposePositions = function (hash) {
-        var tilePositions = this._reconstructions[hash].positions;
+        var tilePositions = this._nodes[hash].positions;
         for (var _i = 0, _a = tilePositions.children.slice(); _i < _a.length; _i++) {
             var position = _a[_i];
             position.geometry.dispose();
@@ -31513,11 +38945,14 @@ var SpatialDataScene = /** @class */ (function () {
         }
         this._scene.remove(tilePositions);
     };
-    SpatialDataScene.prototype._disposeReconstruction = function (hash) {
+    SpatialDataScene.prototype._disposeNodes = function (hash) {
         this._disposeCameras(hash);
-        this._disposePoints(hash);
         this._disposePositions(hash);
-        delete this._reconstructions[hash];
+        delete this._nodes[hash];
+    };
+    SpatialDataScene.prototype._disposeReconstruction = function (hash) {
+        this._disposePoints(hash);
+        delete this._tileClusterReconstructions[hash];
     };
     SpatialDataScene.prototype._disposeTile = function (hash) {
         var tile = this._tiles[hash];
@@ -31530,16 +38965,28 @@ var SpatialDataScene = /** @class */ (function () {
         this._scene.remove(tile);
         delete this._tiles[hash];
     };
-    SpatialDataScene.prototype._getColor = function (connectedComponent, visualizeConnectedComponents) {
-        return visualizeConnectedComponents ?
-            this._getConnectedComponentColor(connectedComponent) :
+    SpatialDataScene.prototype._getColor = function (id, mode) {
+        return mode !== CameraVisualizationMode_1.default.Default && id.length > 0 ?
+            this._getCameraColor(id) :
             "#FFFFFF";
     };
-    SpatialDataScene.prototype._getConnectedComponentColor = function (connectedComponent) {
-        if (!(connectedComponent in this._connectedComponentColors)) {
-            this._connectedComponentColors[connectedComponent] = this._randomColor();
+    SpatialDataScene.prototype._getCameraColor = function (id) {
+        if (!(id in this._cameraColors)) {
+            this._cameraColors[id] = this._randomColor();
+        }
+        return this._cameraColors[id];
+    };
+    SpatialDataScene.prototype._getId = function (clusterKey, connectedComponent, sequenceKey, mode) {
+        switch (mode) {
+            case CameraVisualizationMode_1.default.Cluster:
+                return clusterKey;
+            case CameraVisualizationMode_1.default.ConnectedComponent:
+                return connectedComponent;
+            case CameraVisualizationMode_1.default.Sequence:
+                return sequenceKey;
+            default:
+                return "";
         }
-        return this._connectedComponentColors[connectedComponent];
     };
     SpatialDataScene.prototype._interpolate = function (a, b, alpha) {
         return a + alpha * (b - a);
@@ -31572,19 +39019,23 @@ var SpatialDataScene = /** @class */ (function () {
 exports.SpatialDataScene = SpatialDataScene;
 exports.default = SpatialDataScene;
 
-},{"three":226}],343:[function(require,module,exports){
+},{"./CameraVisualizationMode":356,"three":242}],361:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var GeometryTagError_1 = require("./error/GeometryTagError");
 exports.GeometryTagError = GeometryTagError_1.GeometryTagError;
 var PointGeometry_1 = require("./geometry/PointGeometry");
 exports.PointGeometry = PointGeometry_1.PointGeometry;
+var PointsGeometry_1 = require("./geometry/PointsGeometry");
+exports.PointsGeometry = PointsGeometry_1.PointsGeometry;
 var RectGeometry_1 = require("./geometry/RectGeometry");
 exports.RectGeometry = RectGeometry_1.RectGeometry;
 var PolygonGeometry_1 = require("./geometry/PolygonGeometry");
 exports.PolygonGeometry = PolygonGeometry_1.PolygonGeometry;
 var OutlineTag_1 = require("./tag/OutlineTag");
 exports.OutlineTag = OutlineTag_1.OutlineTag;
+var ExtremePointTag_1 = require("./tag/ExtremePointTag");
+exports.ExtremePointTag = ExtremePointTag_1.ExtremePointTag;
 var SpotTag_1 = require("./tag/SpotTag");
 exports.SpotTag = SpotTag_1.SpotTag;
 var TagDomain_1 = require("./tag/TagDomain");
@@ -31594,7 +39045,7 @@ exports.TagComponent = TagComponent_1.TagComponent;
 var TagMode_1 = require("./TagMode");
 exports.TagMode = TagMode_1.TagMode;
 
-},{"./TagComponent":344,"./TagMode":347,"./error/GeometryTagError":351,"./geometry/PointGeometry":353,"./geometry/PolygonGeometry":354,"./geometry/RectGeometry":355,"./tag/OutlineTag":367,"./tag/SpotTag":370,"./tag/TagDomain":372}],344:[function(require,module,exports){
+},{"./TagComponent":362,"./TagMode":365,"./error/GeometryTagError":369,"./geometry/PointGeometry":371,"./geometry/PointsGeometry":372,"./geometry/PolygonGeometry":373,"./geometry/RectGeometry":374,"./tag/ExtremePointTag":388,"./tag/OutlineTag":392,"./tag/SpotTag":395,"./tag/TagDomain":397}],362:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -31666,6 +39117,7 @@ var TagComponent = /** @class */ (function (_super) {
         _this._viewportCoords = new Geo_1.ViewportCoords();
         _this._createHandlers = {
             "CreatePoint": new Component_1.CreatePointHandler(_this, container, navigator, _this._viewportCoords, _this._tagCreator),
+            "CreatePoints": new Component_1.CreatePointsHandler(_this, container, navigator, _this._viewportCoords, _this._tagCreator),
             "CreatePolygon": new Component_1.CreatePolygonHandler(_this, container, navigator, _this._viewportCoords, _this._tagCreator),
             "CreateRect": new Component_1.CreateRectHandler(_this, container, navigator, _this._viewportCoords, _this._tagCreator),
             "CreateRectDrag": new Component_1.CreateRectDragHandler(_this, container, navigator, _this._viewportCoords, _this._tagCreator),
@@ -31751,6 +39203,70 @@ var TagComponent = /** @class */ (function (_super) {
             this._tagSet.addDeactivated(tags);
         }
     };
+    /**
+     * Calculate the smallest rectangle containing all the points
+     * in the points geometry.
+     *
+     * @description The result may be different depending on if the
+     * current node is an equirectangular panorama or not. If the
+     * current node is an equirectangular panorama the rectangle may
+     * wrap the horizontal border of the image.
+     *
+     * @returns {Promise<Array<number>>} Promise to the rectangle
+     * on the format specified for the {@link RectGeometry} in basic
+     * coordinates.
+     */
+    TagComponent.prototype.calculateRect = function (geometry) {
+        var _this = this;
+        return when.promise(function (resolve, reject) {
+            _this._navigator.stateService.currentTransform$.pipe(operators_1.first(), operators_1.map(function (transform) {
+                return geometry.getRect2d(transform);
+            }))
+                .subscribe(function (rect) {
+                resolve(rect);
+            }, function (error) {
+                reject(error);
+            });
+        });
+    };
+    /**
+     * Force the creation of a geometry programatically using its
+     * current vertices.
+     *
+     * @description The method only has an effect when the tag
+     * mode is either of the following modes:
+     *
+     * TagMode.CreatePoints
+     * TagMode.CreatePolygon
+     * TagMode.CreateRect
+     * TagMode.CreateRectDrag
+     *
+     * In the case of points or polygon creation, only the created
+     * vertices are used, i.e. the mouse position is disregarded.
+     *
+     * In the case of rectangle creation the position of the mouse
+     * at the time of the method call is used as one of the vertices
+     * defining the rectangle.
+     *
+     * @fires TagComponent.geometrycreated
+     *
+     * @example
+     * ```
+     * tagComponent.on("geometrycreated", function(geometry) {
+     *     console.log(geometry);
+     * });
+     *
+     * tagComponent.create();
+     * ```
+     */
+    TagComponent.prototype.create = function () {
+        this._tagCreator.replayedTag$.pipe(operators_1.first(), operators_1.filter(function (tag) {
+            return !!tag;
+        }))
+            .subscribe(function (tag) {
+            tag.create();
+        });
+    };
     /**
      * Change the current tag mode.
      *
@@ -31807,7 +39323,8 @@ var TagComponent = /** @class */ (function (_super) {
      * tags that do not have a fill will also be returned if the point is inside
      * the geometry of the tag. Tags with point geometries can not be retrieved.
      *
-     * No tag ids will be returned for panoramas.
+     * No tag ids will be returned for polygons rendered in cropped panoramas or
+     * rectangles rendered in panoramas.
      *
      * Notice that the pixelPoint argument requires x, y coordinates from pixel space.
      *
@@ -31817,7 +39334,8 @@ var TagComponent = /** @class */ (function (_super) {
      * If no tag at exist the pixel point, an empty array will be returned.
      *
      * @param {Array<number>} pixelPoint - Pixel coordinates on the viewer element.
-     * @returns {Array<string>} Ids of the tags that contain the specified pixel point.
+     * @returns {Promise<Array<string>>} Promise to the ids of the tags that
+     * contain the specified pixel point.
      *
      * @example
      * ```
@@ -31918,12 +39436,12 @@ var TagComponent = /** @class */ (function (_super) {
             }
         });
         this._fireTagsChangedSubscription = this._renderTags$
-            .subscribe(function (tags) {
+            .subscribe(function () {
             _this.fire(TagComponent.tagschanged, _this);
         });
         this._stopCreateSubscription = this._tagCreator.tag$.pipe(operators_1.switchMap(function (tag) {
             return tag != null ?
-                tag.aborted$.pipe(operators_1.map(function (t) { return null; })) :
+                tag.aborted$.pipe(operators_1.map(function () { return null; })) :
                 rxjs_1.empty();
         }))
             .subscribe(function () { _this.changeMode(Component_1.TagMode.Default); });
@@ -31945,16 +39463,16 @@ var TagComponent = /** @class */ (function (_super) {
             _this._tagScene.updateObjects(tag);
         });
         this._updateTagSceneSubscription = this._tagChanged$
-            .subscribe(function (tag) {
+            .subscribe(function () {
             _this._tagScene.update();
         });
-        this._domSubscription = rxjs_1.combineLatest(this._renderTags$.pipe(operators_1.startWith([]), operators_1.tap(function (tags) {
+        this._domSubscription = rxjs_1.combineLatest(this._renderTags$.pipe(operators_1.startWith([]), operators_1.tap(function () {
             _this._container.domRenderer.render$.next({
                 name: _this._name,
                 vnode: _this._tagDomRenderer.clear(),
             });
         })), this._container.renderService.renderCamera$, this._container.spriteService.spriteAtlas$, this._container.renderService.size$, this._tagChanged$.pipe(operators_1.startWith(null)), rxjs_1.merge(this._tagCreator.tag$, this._createGeometryChanged$).pipe(operators_1.startWith(null))).pipe(operators_1.map(function (_a) {
-            var renderTags = _a[0], rc = _a[1], atlas = _a[2], size = _a[3], tag = _a[4], ct = _a[5];
+            var renderTags = _a[0], rc = _a[1], atlas = _a[2], size = _a[3], ct = _a[5];
             return {
                 name: _this._name,
                 vnode: _this._tagDomRenderer.render(renderTags, ct, atlas, rc.perspective, size),
@@ -32003,6 +39521,7 @@ var TagComponent = /** @class */ (function (_super) {
     TagComponent.prototype._getDefaultConfiguration = function () {
         return {
             createColor: 0xFFFFFF,
+            indicatePointsCompleter: true,
             mode: Component_1.TagMode.Default,
         };
     };
@@ -32097,7 +39616,7 @@ exports.TagComponent = TagComponent;
 Component_1.ComponentService.register(TagComponent);
 exports.default = TagComponent;
 
-},{"../../Component":275,"../../Geo":278,"../../Render":281,"rxjs":27,"rxjs/operators":225,"when":272}],345:[function(require,module,exports){
+},{"../../Component":291,"../../Geo":294,"../../Render":297,"rxjs":43,"rxjs/operators":241,"when":288}],363:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
@@ -32108,15 +39627,32 @@ var TagCreator = /** @class */ (function () {
         this._component = component;
         this._navigator = navigator;
         this._tagOperation$ = new rxjs_1.Subject();
+        this._createPoints$ = new rxjs_1.Subject();
         this._createPolygon$ = new rxjs_1.Subject();
         this._createRect$ = new rxjs_1.Subject();
         this._delete$ = new rxjs_1.Subject();
         this._tag$ = this._tagOperation$.pipe(operators_1.scan(function (tag, operation) {
             return operation(tag);
         }, null), operators_1.share());
+        this._replayedTag$ = this._tag$.pipe(operators_1.publishReplay(1), operators_1.refCount());
+        this._replayedTag$.subscribe();
+        this._createPoints$.pipe(operators_1.withLatestFrom(this._component.configuration$, this._navigator.stateService.currentTransform$), operators_1.map(function (_a) {
+            var coord = _a[0], conf = _a[1], transform = _a[2];
+            return function () {
+                var geometry = new Component_1.PointsGeometry([
+                    [coord[0], coord[1]],
+                    [coord[0], coord[1]],
+                ]);
+                return new Component_1.ExtremePointCreateTag(geometry, {
+                    color: conf.createColor,
+                    indicateCompleter: conf.indicatePointsCompleter,
+                }, transform);
+            };
+        }))
+            .subscribe(this._tagOperation$);
         this._createRect$.pipe(operators_1.withLatestFrom(this._component.configuration$, this._navigator.stateService.currentTransform$), operators_1.map(function (_a) {
             var coord = _a[0], conf = _a[1], transform = _a[2];
-            return function (tag) {
+            return function () {
                 var geometry = new Component_1.RectGeometry([
                     coord[0],
                     coord[1],
@@ -32129,7 +39665,7 @@ var TagCreator = /** @class */ (function () {
             .subscribe(this._tagOperation$);
         this._createPolygon$.pipe(operators_1.withLatestFrom(this._component.configuration$, this._navigator.stateService.currentTransform$), operators_1.map(function (_a) {
             var coord = _a[0], conf = _a[1], transform = _a[2];
-            return function (tag) {
+            return function () {
                 var geometry = new Component_1.PolygonGeometry([
                     [coord[0], coord[1]],
                     [coord[0], coord[1]],
@@ -32140,7 +39676,7 @@ var TagCreator = /** @class */ (function () {
         }))
             .subscribe(this._tagOperation$);
         this._delete$.pipe(operators_1.map(function () {
-            return function (tag) {
+            return function () {
                 return null;
             };
         }))
@@ -32160,6 +39696,13 @@ var TagCreator = /** @class */ (function () {
         enumerable: true,
         configurable: true
     });
+    Object.defineProperty(TagCreator.prototype, "createPoints$", {
+        get: function () {
+            return this._createPoints$;
+        },
+        enumerable: true,
+        configurable: true
+    });
     Object.defineProperty(TagCreator.prototype, "delete$", {
         get: function () {
             return this._delete$;
@@ -32174,12 +39717,19 @@ var TagCreator = /** @class */ (function () {
         enumerable: true,
         configurable: true
     });
+    Object.defineProperty(TagCreator.prototype, "replayedTag$", {
+        get: function () {
+            return this._replayedTag$;
+        },
+        enumerable: true,
+        configurable: true
+    });
     return TagCreator;
 }());
 exports.TagCreator = TagCreator;
 exports.default = TagCreator;
 
-},{"../../Component":275,"rxjs":27,"rxjs/operators":225}],346:[function(require,module,exports){
+},{"../../Component":291,"rxjs":43,"rxjs/operators":241}],364:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var vd = require("virtual-dom");
@@ -32204,7 +39754,7 @@ var TagDOMRenderer = /** @class */ (function () {
 }());
 exports.TagDOMRenderer = TagDOMRenderer;
 
-},{"virtual-dom":231}],347:[function(require,module,exports){
+},{"virtual-dom":247}],365:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -32223,25 +39773,29 @@ var TagMode;
      * Create a point geometry through a click.
      */
     TagMode[TagMode["CreatePoint"] = 1] = "CreatePoint";
+    /**
+     * Create a points geometry through clicks.
+     */
+    TagMode[TagMode["CreatePoints"] = 2] = "CreatePoints";
     /**
      * Create a polygon geometry through clicks.
      */
-    TagMode[TagMode["CreatePolygon"] = 2] = "CreatePolygon";
+    TagMode[TagMode["CreatePolygon"] = 3] = "CreatePolygon";
     /**
      * Create a rect geometry through clicks.
      */
-    TagMode[TagMode["CreateRect"] = 3] = "CreateRect";
+    TagMode[TagMode["CreateRect"] = 4] = "CreateRect";
     /**
      * Create a rect geometry through drag.
      *
      * @description Claims the mouse which results in mouse handlers like
      * drag pan and scroll zoom becoming inactive.
      */
-    TagMode[TagMode["CreateRectDrag"] = 4] = "CreateRectDrag";
+    TagMode[TagMode["CreateRectDrag"] = 5] = "CreateRectDrag";
 })(TagMode = exports.TagMode || (exports.TagMode = {}));
 exports.default = TagMode;
 
-},{}],348:[function(require,module,exports){
+},{}],366:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var TagOperation;
@@ -32252,7 +39806,7 @@ var TagOperation;
 })(TagOperation = exports.TagOperation || (exports.TagOperation = {}));
 exports.default = TagOperation;
 
-},{}],349:[function(require,module,exports){
+},{}],367:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
@@ -32419,11 +39973,13 @@ var TagScene = /** @class */ (function () {
 exports.TagScene = TagScene;
 exports.default = TagScene;
 
-},{"three":226}],350:[function(require,module,exports){
+},{"three":242}],368:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
 var Component_1 = require("../../Component");
+var ExtremePointTag_1 = require("./tag/ExtremePointTag");
+var ExtremePointRenderTag_1 = require("./tag/ExtremePointRenderTag");
 var TagSet = /** @class */ (function () {
     function TagSet() {
         this._active = false;
@@ -32485,7 +40041,9 @@ var TagSet = /** @class */ (function () {
         this._assertActivationState(false);
         for (var _i = 0, tags_2 = tags; _i < tags_2.length; _i++) {
             var tag = tags_2[_i];
-            if (!(tag instanceof Component_1.OutlineTag || tag instanceof Component_1.SpotTag)) {
+            if (!(tag instanceof Component_1.OutlineTag ||
+                tag instanceof Component_1.SpotTag ||
+                tag instanceof ExtremePointTag_1.default)) {
                 throw new Error("Tag type not supported");
             }
             this._hashDeactivated[tag.id] = tag;
@@ -32556,6 +40114,9 @@ var TagSet = /** @class */ (function () {
         else if (tag instanceof Component_1.SpotTag) {
             this._hash[tag.id] = new Component_1.SpotRenderTag(tag, transform);
         }
+        else if (tag instanceof ExtremePointTag_1.default) {
+            this._hash[tag.id] = new ExtremePointRenderTag_1.default(tag, transform);
+        }
         else {
             throw new Error("Tag type not supported");
         }
@@ -32570,7 +40131,7 @@ var TagSet = /** @class */ (function () {
 exports.TagSet = TagSet;
 exports.default = TagSet;
 
-},{"../../Component":275,"rxjs":27}],351:[function(require,module,exports){
+},{"../../Component":291,"./tag/ExtremePointRenderTag":387,"./tag/ExtremePointTag":388,"rxjs":43}],369:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -32591,6 +40152,7 @@ var GeometryTagError = /** @class */ (function (_super) {
     __extends(GeometryTagError, _super);
     function GeometryTagError(message) {
         var _this = _super.call(this, message != null ? message : "The provided geometry value is incorrect") || this;
+        Object.setPrototypeOf(_this, GeometryTagError.prototype);
         _this.name = "GeometryTagError";
         return _this;
     }
@@ -32599,7 +40161,7 @@ var GeometryTagError = /** @class */ (function (_super) {
 exports.GeometryTagError = GeometryTagError;
 exports.default = Error_1.MapillaryError;
 
-},{"../../../Error":277}],352:[function(require,module,exports){
+},{"../../../Error":293}],370:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -32639,7 +40201,7 @@ var Geometry = /** @class */ (function () {
 exports.Geometry = Geometry;
 exports.default = Geometry;
 
-},{"rxjs":27}],353:[function(require,module,exports){
+},{"rxjs":43}],371:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -32739,8 +40301,224 @@ var PointGeometry = /** @class */ (function (_super) {
     return PointGeometry;
 }(Component_1.Geometry));
 exports.PointGeometry = PointGeometry;
+exports.default = PointGeometry;
+
+},{"../../../Component":291}],372:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    }
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Component_1 = require("../../../Component");
+/**
+ * @class PointsGeometry
+ *
+ * @classdesc Represents a point set in the 2D basic image coordinate system.
+ *
+ * @example
+ * ```
+ * var points = [[0.5, 0.3], [0.7, 0.3], [0.6, 0.5]];
+ * var pointsGeometry = new Mapillary.TagComponent.PointsGeometry(points);
+ * ```
+ */
+var PointsGeometry = /** @class */ (function (_super) {
+    __extends(PointsGeometry, _super);
+    /**
+     * Create a points geometry.
+     *
+     * @constructor
+     * @param {Array<Array<number>>} points - Array of 2D points on the basic coordinate
+     * system. The number of points must be greater than or equal to two.
+     *
+     * @throws {GeometryTagError} Point coordinates must be valid basic coordinates.
+     */
+    function PointsGeometry(points) {
+        var _this = _super.call(this) || this;
+        var pointsLength = points.length;
+        if (pointsLength < 2) {
+            throw new Component_1.GeometryTagError("A points geometry must have two or more positions.");
+        }
+        _this._points = [];
+        for (var _i = 0, points_1 = points; _i < points_1.length; _i++) {
+            var point = points_1[_i];
+            if (point[0] < 0 || point[0] > 1 ||
+                point[1] < 0 || point[1] > 1) {
+                throw new Component_1.GeometryTagError("Basic coordinates of points must be on the interval [0, 1].");
+            }
+            _this._points.push(point.slice());
+        }
+        return _this;
+    }
+    Object.defineProperty(PointsGeometry.prototype, "points", {
+        /**
+         * Get points property.
+         * @returns {Array<Array<number>>} Array of 2d points.
+         */
+        get: function () {
+            return this._points;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    /**
+     * Add a point to the point set.
+     *
+     * @param {Array<number>} point - Point to add.
+     * @ignore
+     */
+    PointsGeometry.prototype.addPoint2d = function (point) {
+        var clamped = [
+            Math.max(0, Math.min(1, point[0])),
+            Math.max(0, Math.min(1, point[1])),
+        ];
+        this._points.push(clamped);
+        this._notifyChanged$.next(this);
+    };
+    /**
+     * Get the coordinates of a point from the point set representation of the geometry.
+     *
+     * @param {number} index - Point index.
+     * @returns {Array<number>} Array representing the 2D basic coordinates of the point.
+     * @ignore
+     */
+    PointsGeometry.prototype.getPoint2d = function (index) {
+        return this._points[index].slice();
+    };
+    /**
+     * Remove a point from the point set.
+     *
+     * @param {number} index - The index of the point to remove.
+     * @ignore
+     */
+    PointsGeometry.prototype.removePoint2d = function (index) {
+        if (index < 0 ||
+            index >= this._points.length ||
+            this._points.length < 3) {
+            throw new Component_1.GeometryTagError("Index for removed point must be valid.");
+        }
+        this._points.splice(index, 1);
+        this._notifyChanged$.next(this);
+    };
+    /** @ignore */
+    PointsGeometry.prototype.setVertex2d = function (index, value, transform) {
+        this.setPoint2d(index, value, transform);
+    };
+    /** @ignore */
+    PointsGeometry.prototype.setPoint2d = function (index, value, transform) {
+        var changed = [
+            Math.max(0, Math.min(1, value[0])),
+            Math.max(0, Math.min(1, value[1])),
+        ];
+        this._points[index] = changed;
+        this._notifyChanged$.next(this);
+    };
+    /** @ignore */
+    PointsGeometry.prototype.getPoints3d = function (transform) {
+        return this._getPoints3d(this._points, transform);
+    };
+    /** @ignore */
+    PointsGeometry.prototype.getPoint3d = function (index, transform) {
+        return transform.unprojectBasic(this._points[index], 200);
+    };
+    /** @ignore */
+    PointsGeometry.prototype.getPoints2d = function () {
+        return this._points.slice();
+    };
+    /** @ignore */
+    PointsGeometry.prototype.getCentroid2d = function (transform) {
+        if (!transform) {
+            throw new Component_1.GeometryTagError("Get centroid must be called with a transform for points geometries.");
+        }
+        var _a = this.getRect2d(transform), minX = _a[0], minY = _a[1], maxX = _a[2], maxY = _a[3];
+        var centroidX = minX < maxX ?
+            (minX + maxX) / 2 :
+            ((minX + maxX + 1) / 2) % 1;
+        var centroidY = (minY + maxY) / 2;
+        return [centroidX, centroidY];
+    };
+    /** @ignore */
+    PointsGeometry.prototype.getCentroid3d = function (transform) {
+        var centroid2d = this.getCentroid2d();
+        return transform.unprojectBasic(centroid2d, 200);
+    };
+    /** @ignore */
+    PointsGeometry.prototype.getRect2d = function (transform) {
+        var minX = 1;
+        var maxX = 0;
+        var minY = 1;
+        var maxY = 0;
+        var points = this._points;
+        for (var _i = 0, points_2 = points; _i < points_2.length; _i++) {
+            var point = points_2[_i];
+            if (point[0] < minX) {
+                minX = point[0];
+            }
+            if (point[0] > maxX) {
+                maxX = point[0];
+            }
+            if (point[1] < minY) {
+                minY = point[1];
+            }
+            if (point[1] > maxY) {
+                maxY = point[1];
+            }
+        }
+        if (transform.fullPano) {
+            var indices = [];
+            for (var i = 0; i < points.length; i++) {
+                indices[i] = i;
+            }
+            indices.sort(function (a, b) {
+                return points[a][0] < points[b][0] ?
+                    -1 :
+                    points[a][0] > points[b][0] ?
+                        1 :
+                        a < b ? -1 : 1;
+            });
+            var maxDistanceX = points[indices[0]][0] + 1 - points[indices[indices.length - 1]][0];
+            var leftMostIndex = 0;
+            for (var i = 0; i < indices.length - 1; i++) {
+                var index1 = indices[i];
+                var index2 = indices[i + 1];
+                var distanceX = points[index2][0] - points[index1][0];
+                if (distanceX > maxDistanceX) {
+                    maxDistanceX = distanceX;
+                    leftMostIndex = i + 1;
+                }
+            }
+            if (leftMostIndex > 0) {
+                minX = points[indices[leftMostIndex]][0];
+                maxX = points[indices[leftMostIndex - 1]][0];
+            }
+        }
+        return [minX, minY, maxX, maxY];
+    };
+    /** @ignore */
+    PointsGeometry.prototype.setCentroid2d = function (value, transform) {
+        throw new Error("Not implemented");
+    };
+    PointsGeometry.prototype._getPoints3d = function (points2d, transform) {
+        return points2d
+            .map(function (point) {
+            return transform.unprojectBasic(point, 200);
+        });
+    };
+    return PointsGeometry;
+}(Component_1.Geometry));
+exports.PointsGeometry = PointsGeometry;
+exports.default = PointsGeometry;
 
-},{"../../../Component":275}],354:[function(require,module,exports){
+},{"../../../Component":291}],373:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -32865,9 +40643,6 @@ var PolygonGeometry = /** @class */ (function (_super) {
     /**
      * Get the coordinates of a vertex from the polygon representation of the geometry.
      *
-     * @description The first vertex represents the bottom-left corner with the rest of
-     * the vertices following in clockwise order.
-     *
      * @param {number} index - Vertex index.
      * @returns {Array<number>} Array representing the 2D basic coordinates of the vertex.
      * @ignore
@@ -33053,7 +40828,7 @@ var PolygonGeometry = /** @class */ (function (_super) {
 exports.PolygonGeometry = PolygonGeometry;
 exports.default = PolygonGeometry;
 
-},{"../../../Component":275}],355:[function(require,module,exports){
+},{"../../../Component":291}],374:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -33717,7 +41492,7 @@ var RectGeometry = /** @class */ (function (_super) {
 exports.RectGeometry = RectGeometry;
 exports.default = RectGeometry;
 
-},{"../../../Component":275}],356:[function(require,module,exports){
+},{"../../../Component":291}],375:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -33912,7 +41687,7 @@ var VertexGeometry = /** @class */ (function (_super) {
 exports.VertexGeometry = VertexGeometry;
 exports.default = VertexGeometry;
 
-},{"../../../Component":275,"@mapbox/polylabel":1,"earcut":8,"martinez-polygon-clipping":22,"three":226}],357:[function(require,module,exports){
+},{"../../../Component":291,"@mapbox/polylabel":1,"earcut":8,"martinez-polygon-clipping":22,"three":242}],376:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -33971,7 +41746,7 @@ var CreateHandlerBase = /** @class */ (function (_super) {
 exports.CreateHandlerBase = CreateHandlerBase;
 exports.default = CreateHandlerBase;
 
-},{"../../../Component":275,"rxjs":27,"rxjs/operators":225}],358:[function(require,module,exports){
+},{"../../../Component":291,"rxjs":43,"rxjs/operators":241}],377:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -34013,7 +41788,50 @@ var CreatePointHandler = /** @class */ (function (_super) {
 exports.CreatePointHandler = CreatePointHandler;
 exports.default = CreatePointHandler;
 
-},{"../../../Component":275,"rxjs/operators":225}],359:[function(require,module,exports){
+},{"../../../Component":291,"rxjs/operators":241}],378:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    }
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Component_1 = require("../../../Component");
+var CreatePointsHandler = /** @class */ (function (_super) {
+    __extends(CreatePointsHandler, _super);
+    function CreatePointsHandler() {
+        return _super !== null && _super.apply(this, arguments) || this;
+    }
+    CreatePointsHandler.prototype._addPoint = function (tag, basicPoint) {
+        tag.geometry.addPoint2d(basicPoint);
+    };
+    Object.defineProperty(CreatePointsHandler.prototype, "_create$", {
+        get: function () {
+            return this._tagCreator.createPoints$;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    CreatePointsHandler.prototype._getNameExtension = function () {
+        return "create-points";
+    };
+    CreatePointsHandler.prototype._setVertex2d = function (tag, basicPoint, transform) {
+        tag.geometry.setPoint2d((tag.geometry).points.length - 1, basicPoint, transform);
+    };
+    return CreatePointsHandler;
+}(Component_1.CreateVertexHandler));
+exports.CreatePointsHandler = CreatePointsHandler;
+exports.default = CreatePointsHandler;
+
+},{"../../../Component":291}],379:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -34056,7 +41874,7 @@ var CreatePolygonHandler = /** @class */ (function (_super) {
 exports.CreatePolygonHandler = CreatePolygonHandler;
 exports.default = CreatePolygonHandler;
 
-},{"../../../Component":275}],360:[function(require,module,exports){
+},{"../../../Component":291}],380:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -34149,7 +41967,7 @@ var CreateRectDragHandler = /** @class */ (function (_super) {
 exports.CreateRectDragHandler = CreateRectDragHandler;
 exports.default = CreateRectDragHandler;
 
-},{"../../../Component":275,"rxjs":27,"rxjs/operators":225}],361:[function(require,module,exports){
+},{"../../../Component":291,"rxjs":43,"rxjs/operators":241}],381:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -34210,7 +42028,7 @@ var CreateRectHandler = /** @class */ (function (_super) {
 exports.CreateRectHandler = CreateRectHandler;
 exports.default = CreateRectHandler;
 
-},{"../../../Component":275,"rxjs/operators":225}],362:[function(require,module,exports){
+},{"../../../Component":291,"rxjs/operators":241}],382:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -34237,7 +42055,7 @@ var CreateVertexHandler = /** @class */ (function (_super) {
     CreateVertexHandler.prototype._enableCreate = function () {
         var _this = this;
         this._container.mouseService.deferPixels(this._name, 4);
-        var transformChanged$ = this._navigator.stateService.currentTransform$.pipe(operators_1.map(function (transform) { }), operators_1.publishReplay(1), operators_1.refCount());
+        var transformChanged$ = this._navigator.stateService.currentTransform$.pipe(operators_1.map(function () { }), operators_1.publishReplay(1), operators_1.refCount());
         this._deleteSubscription = transformChanged$.pipe(operators_1.skip(1))
             .subscribe(this._tagCreator.delete$);
         var basicClick$ = this._mouseEventToBasic$(this._container.mouseService.proximateClick$).pipe(operators_1.share());
@@ -34287,7 +42105,7 @@ var CreateVertexHandler = /** @class */ (function (_super) {
 exports.CreateVertexHandler = CreateVertexHandler;
 exports.default = CreateVertexHandler;
 
-},{"../../../Component":275,"rxjs":27,"rxjs/operators":225}],363:[function(require,module,exports){
+},{"../../../Component":291,"rxjs":43,"rxjs/operators":241}],383:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -34400,7 +42218,7 @@ exports.EditVertexHandler = EditVertexHandler;
 exports.default = EditVertexHandler;
 
 
-},{"../../../Component":275,"rxjs":27,"rxjs/operators":225}],364:[function(require,module,exports){
+},{"../../../Component":291,"rxjs":43,"rxjs/operators":241}],384:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -34441,84 +42259,678 @@ exports.TagHandlerBase = TagHandlerBase;
 exports.default = TagHandlerBase;
 
 
-},{"../../../Component":275}],365:[function(require,module,exports){
+},{"../../../Component":291}],385:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
 var THREE = require("three");
-var vd = require("virtual-dom");
 var rxjs_1 = require("rxjs");
-var Component_1 = require("../../../Component");
 var Geo_1 = require("../../../Geo");
-var OutlineCreateTag = /** @class */ (function () {
-    function OutlineCreateTag(geometry, options, transform, viewportCoords) {
+var CreateTag = /** @class */ (function () {
+    function CreateTag(geometry, transform, viewportCoords) {
         var _this = this;
         this._geometry = geometry;
-        this._options = { color: options.color == null ? 0xFFFFFF : options.color };
         this._transform = transform;
         this._viewportCoords = !!viewportCoords ? viewportCoords : new Geo_1.ViewportCoords();
-        this._outline = this._createOutine();
-        this._glObjects = [this._outline];
         this._aborted$ = new rxjs_1.Subject();
         this._created$ = new rxjs_1.Subject();
         this._glObjectsChanged$ = new rxjs_1.Subject();
         this._geometryChangedSubscription = this._geometry.changed$
-            .subscribe(function (vertexGeometry) {
-            _this._disposeOutline();
-            _this._outline = _this._createOutine();
-            _this._glObjects = [_this._outline];
+            .subscribe(function () {
+            _this._onGeometryChanged();
             _this._glObjectsChanged$.next(_this);
         });
     }
-    Object.defineProperty(OutlineCreateTag.prototype, "geometry", {
+    Object.defineProperty(CreateTag.prototype, "geometry", {
         get: function () {
             return this._geometry;
         },
         enumerable: true,
         configurable: true
     });
-    Object.defineProperty(OutlineCreateTag.prototype, "glObjects", {
+    Object.defineProperty(CreateTag.prototype, "glObjects", {
         get: function () {
             return this._glObjects;
         },
         enumerable: true,
         configurable: true
     });
-    Object.defineProperty(OutlineCreateTag.prototype, "aborted$", {
+    Object.defineProperty(CreateTag.prototype, "aborted$", {
         get: function () {
             return this._aborted$;
         },
         enumerable: true,
         configurable: true
     });
-    Object.defineProperty(OutlineCreateTag.prototype, "created$", {
+    Object.defineProperty(CreateTag.prototype, "created$", {
         get: function () {
             return this._created$;
         },
         enumerable: true,
         configurable: true
     });
-    Object.defineProperty(OutlineCreateTag.prototype, "glObjectsChanged$", {
+    Object.defineProperty(CreateTag.prototype, "glObjectsChanged$", {
         get: function () {
             return this._glObjectsChanged$;
         },
         enumerable: true,
         configurable: true
     });
-    Object.defineProperty(OutlineCreateTag.prototype, "geometryChanged$", {
+    Object.defineProperty(CreateTag.prototype, "geometryChanged$", {
         get: function () {
             var _this = this;
-            return this._geometry.changed$.pipe(operators_1.map(function (geometry) {
+            return this._geometry.changed$.pipe(operators_1.map(function () {
                 return _this;
             }));
         },
         enumerable: true,
         configurable: true
     });
-    OutlineCreateTag.prototype.dispose = function () {
-        this._disposeOutline();
+    CreateTag.prototype.dispose = function () {
         this._geometryChangedSubscription.unsubscribe();
     };
+    CreateTag.prototype._canvasToTransform = function (canvas) {
+        var canvasX = Math.round(canvas[0]);
+        var canvasY = Math.round(canvas[1]);
+        var transform = "translate(-50%,-50%) translate(" + canvasX + "px," + canvasY + "px)";
+        return transform;
+    };
+    CreateTag.prototype._colorToBackground = function (color) {
+        return "#" + ("000000" + color.toString(16)).substr(-6);
+    };
+    CreateTag.prototype._createOutine = function (polygon3d, color) {
+        var positions = this._getLinePositions(polygon3d);
+        var geometry = new THREE.BufferGeometry();
+        geometry.addAttribute("position", new THREE.BufferAttribute(positions, 3));
+        var material = new THREE.LineBasicMaterial({
+            color: color,
+            linewidth: 1,
+        });
+        return new THREE.Line(geometry, material);
+    };
+    CreateTag.prototype._disposeLine = function (line) {
+        if (line == null) {
+            return;
+        }
+        line.geometry.dispose();
+        line.material.dispose();
+    };
+    CreateTag.prototype._getLinePositions = function (polygon3d) {
+        var length = polygon3d.length;
+        var positions = new Float32Array(length * 3);
+        for (var i = 0; i < length; ++i) {
+            var index = 3 * i;
+            var position = polygon3d[i];
+            positions[index] = position[0];
+            positions[index + 1] = position[1];
+            positions[index + 2] = position[2];
+        }
+        return positions;
+    };
+    return CreateTag;
+}());
+exports.CreateTag = CreateTag;
+exports.default = CreateTag;
+
+},{"../../../Geo":294,"rxjs":43,"rxjs/operators":241,"three":242}],386:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    }
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var vd = require("virtual-dom");
+var Tag_1 = require("../Tag");
+var Component_1 = require("../../../Component");
+var ExtremePointCreateTag = /** @class */ (function (_super) {
+    __extends(ExtremePointCreateTag, _super);
+    function ExtremePointCreateTag(geometry, options, transform, viewportCoords) {
+        var _this = _super.call(this, geometry, transform, viewportCoords) || this;
+        _this._options = {
+            color: options.color == null ? 0xFFFFFF : options.color,
+            indicateCompleter: options.indicateCompleter == null ? true : options.indicateCompleter,
+        };
+        _this._rectGeometry = new Tag_1.RectGeometry(_this._geometry.getRect2d(transform));
+        _this._createGlObjects();
+        return _this;
+    }
+    ExtremePointCreateTag.prototype.create = function () {
+        if (this._geometry.points.length < 3) {
+            return;
+        }
+        this._geometry.removePoint2d(this._geometry.points.length - 1);
+        this._created$.next(this);
+    };
+    ExtremePointCreateTag.prototype.dispose = function () {
+        _super.prototype.dispose.call(this);
+        this._disposeObjects();
+    };
+    ExtremePointCreateTag.prototype.getDOMObjects = function (camera, size) {
+        var _this = this;
+        var container = {
+            offsetHeight: size.height, offsetWidth: size.width,
+        };
+        var vNodes = [];
+        var points2d = this._geometry.getPoints2d();
+        var length = points2d.length;
+        var _loop_1 = function (index) {
+            var nonModifiedIndex = index;
+            var _a = points2d[index], pointX = _a[0], pointY = _a[1];
+            var pointCanvas = this_1._viewportCoords.basicToCanvasSafe(pointX, pointY, container, this_1._transform, camera);
+            if (!pointCanvas) {
+                return "continue";
+            }
+            var abort = function (e) {
+                e.stopPropagation();
+                _this._aborted$.next(_this);
+            };
+            var remove = function (e) {
+                e.stopPropagation();
+                _this._geometry.removePoint2d(nonModifiedIndex);
+            };
+            var transform = this_1._canvasToTransform(pointCanvas);
+            var completerProperties = {
+                onclick: index === 0 && length < 3 ? abort : remove,
+                style: { transform: transform },
+            };
+            vNodes.push(vd.h("div.TagInteractor", completerProperties, []));
+            var background = this_1._colorToBackground(this_1._options.color);
+            var pointProperties = {
+                style: {
+                    background: background,
+                    transform: transform,
+                },
+            };
+            vNodes.push(vd.h("div.TagVertex", pointProperties, []));
+        };
+        var this_1 = this;
+        for (var index = 0; index < length - 1; index++) {
+            _loop_1(index);
+        }
+        if (length > 2 && this._options.indicateCompleter === true) {
+            var _a = this._geometry.getCentroid2d(this._transform), centroidX = _a[0], centroidY = _a[1];
+            var centroidCanvas = this._viewportCoords.basicToCanvasSafe(centroidX, centroidY, container, this._transform, camera);
+            if (!!centroidCanvas) {
+                var complete = function (e) {
+                    e.stopPropagation();
+                    _this._geometry.removePoint2d(_this._geometry.points.length - 1);
+                    _this._created$.next(_this);
+                };
+                var transform = this._canvasToTransform(centroidCanvas);
+                var completerProperties = {
+                    onclick: complete,
+                    style: { transform: transform },
+                };
+                vNodes.push(vd.h("div.TagCompleter.TagLarger", completerProperties, []));
+                var pointProperties = {
+                    style: {
+                        background: this._colorToBackground(this._options.color),
+                        transform: transform,
+                    },
+                };
+                vNodes.push(vd.h("div.TagVertex.TagLarger", pointProperties, []));
+                var dotProperties = {
+                    style: {
+                        transform: transform,
+                    },
+                };
+                vNodes.push(vd.h("div.TagDot", dotProperties, []));
+            }
+        }
+        return vNodes;
+    };
+    ExtremePointCreateTag.prototype._onGeometryChanged = function () {
+        this._disposeObjects();
+        this._rectGeometry = new Tag_1.RectGeometry(this._geometry.getRect2d(this._transform));
+        this._createGlObjects();
+    };
+    ExtremePointCreateTag.prototype._createGlObjects = function () {
+        this._glObjects = [];
+        var polygon3d = this._rectGeometry.getPoints3d(this._transform);
+        this._outline = this._createOutine(polygon3d, this._options.color);
+        this._glObjects.push(this._outline);
+    };
+    ExtremePointCreateTag.prototype._disposeObjects = function () {
+        this._disposeLine(this._outline);
+        this._outline = null;
+        this._glObjects = null;
+    };
+    return ExtremePointCreateTag;
+}(Component_1.CreateTag));
+exports.ExtremePointCreateTag = ExtremePointCreateTag;
+
+
+},{"../../../Component":291,"../Tag":361,"virtual-dom":247}],387:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    }
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var THREE = require("three");
+var vd = require("virtual-dom");
+var Component_1 = require("../../../Component");
+/**
+ * @class OutlineRenderTag
+ * @classdesc Tag visualizing the properties of an OutlineTag.
+ */
+var ExtremePointRenderTag = /** @class */ (function (_super) {
+    __extends(ExtremePointRenderTag, _super);
+    function ExtremePointRenderTag(tag, transform) {
+        var _this = _super.call(this, tag, transform) || this;
+        _this._rectGeometry = new Component_1.RectGeometry(_this._tag.geometry.getRect2d(transform));
+        _this._fill = !transform.gpano ?
+            _this._createFill() : null;
+        _this._outline = _this._tag.lineWidth >= 1 ?
+            _this._createOutline() :
+            null;
+        return _this;
+    }
+    ExtremePointRenderTag.prototype.dispose = function () {
+        _super.prototype.dispose.call(this);
+        this._disposeFill();
+        this._disposeOutline();
+    };
+    ExtremePointRenderTag.prototype.getDOMObjects = function (atlas, camera, size) {
+        var vNodes = [];
+        var container = {
+            offsetHeight: size.height, offsetWidth: size.width,
+        };
+        if (!this._tag.editable) {
+            return vNodes;
+        }
+        var lineColor = this._colorToCss(this._tag.lineColor);
+        var points2d = this._tag.geometry.getPoints2d();
+        for (var i = 0; i < points2d.length; i++) {
+            var _a = points2d[i], vertexBasicX = _a[0], vertexBasicY = _a[1];
+            var vertexCanvas = this._viewportCoords.basicToCanvasSafe(vertexBasicX, vertexBasicY, container, this._transform, camera);
+            if (vertexCanvas == null) {
+                continue;
+            }
+            var cursor = "crosshair";
+            var interact = this._interact(Component_1.TagOperation.Vertex, cursor, i);
+            var vertexCanvasX = Math.round(vertexCanvas[0]);
+            var vertexCanvasY = Math.round(vertexCanvas[1]);
+            var transform = "translate(-50%, -50%) translate(" + vertexCanvasX + "px," + vertexCanvasY + "px)";
+            var properties = {
+                onmousedown: interact,
+                style: { background: lineColor, transform: transform, cursor: cursor },
+            };
+            vNodes.push(vd.h("div.TagResizer", properties, []));
+            if (!this._tag.indicateVertices) {
+                continue;
+            }
+            var pointProperties = {
+                style: { background: lineColor, transform: transform },
+            };
+            vNodes.push(vd.h("div.TagVertex", pointProperties, []));
+        }
+        return vNodes;
+    };
+    ExtremePointRenderTag.prototype.getGLObjects = function () {
+        var glObjects = [];
+        if (this._fill != null) {
+            glObjects.push(this._fill);
+        }
+        if (this._outline != null) {
+            glObjects.push(this._outline);
+        }
+        return glObjects;
+    };
+    ExtremePointRenderTag.prototype.getRetrievableObjects = function () {
+        return this._fill != null ? [this._fill] : [];
+    };
+    ExtremePointRenderTag.prototype._onGeometryChanged = function () {
+        this._rectGeometry = new Component_1.RectGeometry(this._tag.geometry.getRect2d(this._transform));
+        if (this._fill != null) {
+            this._updateFillGeometry();
+        }
+        if (this._outline != null) {
+            this._updateOulineGeometry();
+        }
+    };
+    ExtremePointRenderTag.prototype._onTagChanged = function () {
+        var glObjectsChanged = false;
+        if (this._fill != null) {
+            this._updateFillMaterial(this._fill.material);
+        }
+        if (this._outline == null) {
+            if (this._tag.lineWidth >= 1) {
+                this._outline = this._createOutline();
+                glObjectsChanged = true;
+            }
+        }
+        else {
+            this._updateOutlineMaterial();
+        }
+        return glObjectsChanged;
+    };
+    ExtremePointRenderTag.prototype._getPoints3d = function () {
+        return this._rectGeometry.getPoints3d(this._transform);
+    };
+    ExtremePointRenderTag.prototype._getTriangles = function () {
+        return this._rectGeometry.getTriangles3d(this._transform);
+    };
+    ExtremePointRenderTag.prototype._updateFillMaterial = function (material) {
+        material.color = new THREE.Color(this._tag.fillColor);
+        material.opacity = this._tag.fillOpacity;
+        material.needsUpdate = true;
+    };
+    ExtremePointRenderTag.prototype._updateLineBasicMaterial = function (material) {
+        material.color = new THREE.Color(this._tag.lineColor);
+        material.linewidth = Math.max(this._tag.lineWidth, 1);
+        material.visible = this._tag.lineWidth >= 1 && this._tag.lineOpacity > 0;
+        material.opacity = this._tag.lineOpacity;
+        material.transparent = this._tag.lineOpacity < 1;
+        material.needsUpdate = true;
+    };
+    ExtremePointRenderTag.prototype._updateOutlineMaterial = function () {
+        var material = this._outline.material;
+        this._updateLineBasicMaterial(material);
+    };
+    return ExtremePointRenderTag;
+}(Component_1.OutlineRenderTagBase));
+exports.ExtremePointRenderTag = ExtremePointRenderTag;
+exports.default = ExtremePointRenderTag;
+
+
+},{"../../../Component":291,"three":242,"virtual-dom":247}],388:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    }
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var Component_1 = require("../../../Component");
+/**
+ * @class ExtremePointTag
+ *
+ * @classdesc Tag holding properties for visualizing a extreme points
+ * and their outline.
+ *
+ * @example
+ * ```
+ * var geometry = new Mapillary.TagComponent.PointsGeometry([[0.3, 0.3], [0.5, 0.4]]);
+ * var tag = new Mapillary.TagComponent.ExtremePointTag(
+ *     "id-1",
+ *     geometry
+ *     { editable: true, lineColor: 0xff0000 });
+ *
+ * tagComponent.add([tag]);
+ * ```
+ */
+var ExtremePointTag = /** @class */ (function (_super) {
+    __extends(ExtremePointTag, _super);
+    /**
+     * Create an extreme point tag.
+     *
+     * @override
+     * @constructor
+     * @param {string} id - Unique identifier of the tag.
+     * @param {PointsGeometry} geometry - Geometry defining points of tag.
+     * @param {IExtremePointTagOptions} options - Options defining the visual appearance and
+     * behavior of the extreme point tag.
+     */
+    function ExtremePointTag(id, geometry, options) {
+        var _this = _super.call(this, id, geometry) || this;
+        options = !!options ? options : {};
+        _this._editable = options.editable == null ? false : options.editable;
+        _this._fillColor = options.fillColor == null ? 0xFFFFFF : options.fillColor;
+        _this._fillOpacity = options.fillOpacity == null ? 0.0 : options.fillOpacity;
+        _this._indicateVertices = options.indicateVertices == null ? true : options.indicateVertices;
+        _this._lineColor = options.lineColor == null ? 0xFFFFFF : options.lineColor;
+        _this._lineOpacity = options.lineOpacity == null ? 1 : options.lineOpacity;
+        _this._lineWidth = options.lineWidth == null ? 1 : options.lineWidth;
+        return _this;
+    }
+    Object.defineProperty(ExtremePointTag.prototype, "editable", {
+        /**
+         * Get editable property.
+         * @returns {boolean} Value indicating if tag is editable.
+         */
+        get: function () {
+            return this._editable;
+        },
+        /**
+         * Set editable property.
+         * @param {boolean}
+         *
+         * @fires Tag#changed
+         */
+        set: function (value) {
+            this._editable = value;
+            this._notifyChanged$.next(this);
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(ExtremePointTag.prototype, "fillColor", {
+        /**
+         * Get fill color property.
+         * @returns {number}
+         */
+        get: function () {
+            return this._fillColor;
+        },
+        /**
+         * Set fill color property.
+         * @param {number}
+         *
+         * @fires Tag#changed
+         */
+        set: function (value) {
+            this._fillColor = value;
+            this._notifyChanged$.next(this);
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(ExtremePointTag.prototype, "fillOpacity", {
+        /**
+         * Get fill opacity property.
+         * @returns {number}
+         */
+        get: function () {
+            return this._fillOpacity;
+        },
+        /**
+         * Set fill opacity property.
+         * @param {number}
+         *
+         * @fires Tag#changed
+         */
+        set: function (value) {
+            this._fillOpacity = value;
+            this._notifyChanged$.next(this);
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(ExtremePointTag.prototype, "geometry", {
+        /** @inheritdoc */
+        get: function () {
+            return this._geometry;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(ExtremePointTag.prototype, "indicateVertices", {
+        /**
+         * Get indicate vertices property.
+         * @returns {boolean} Value indicating if vertices should be indicated
+         * when tag is editable.
+         */
+        get: function () {
+            return this._indicateVertices;
+        },
+        /**
+         * Set indicate vertices property.
+         * @param {boolean}
+         *
+         * @fires Tag#changed
+         */
+        set: function (value) {
+            this._indicateVertices = value;
+            this._notifyChanged$.next(this);
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(ExtremePointTag.prototype, "lineColor", {
+        /**
+         * Get line color property.
+         * @returns {number}
+         */
+        get: function () {
+            return this._lineColor;
+        },
+        /**
+         * Set line color property.
+         * @param {number}
+         *
+         * @fires Tag#changed
+         */
+        set: function (value) {
+            this._lineColor = value;
+            this._notifyChanged$.next(this);
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(ExtremePointTag.prototype, "lineOpacity", {
+        /**
+         * Get line opacity property.
+         * @returns {number}
+         */
+        get: function () {
+            return this._lineOpacity;
+        },
+        /**
+         * Set line opacity property.
+         * @param {number}
+         *
+         * @fires Tag#changed
+         */
+        set: function (value) {
+            this._lineOpacity = value;
+            this._notifyChanged$.next(this);
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(ExtremePointTag.prototype, "lineWidth", {
+        /**
+         * Get line width property.
+         * @returns {number}
+         */
+        get: function () {
+            return this._lineWidth;
+        },
+        /**
+         * Set line width property.
+         * @param {number}
+         *
+         * @fires Tag#changed
+         */
+        set: function (value) {
+            this._lineWidth = value;
+            this._notifyChanged$.next(this);
+        },
+        enumerable: true,
+        configurable: true
+    });
+    /**
+     * Set options for tag.
+     *
+     * @description Sets all the option properties provided and keeps
+     * the rest of the values as is.
+     *
+     * @param {IExtremePointTagOptions} options - Extreme point tag options
+     *
+     * @fires {Tag#changed}
+     */
+    ExtremePointTag.prototype.setOptions = function (options) {
+        this._editable = options.editable == null ? this._editable : options.editable;
+        this._indicateVertices = options.indicateVertices == null ? this._indicateVertices : options.indicateVertices;
+        this._lineColor = options.lineColor == null ? this._lineColor : options.lineColor;
+        this._lineWidth = options.lineWidth == null ? this._lineWidth : options.lineWidth;
+        this._fillColor = options.fillColor == null ? this._fillColor : options.fillColor;
+        this._fillOpacity = options.fillOpacity == null ? this._fillOpacity : options.fillOpacity;
+        this._notifyChanged$.next(this);
+    };
+    return ExtremePointTag;
+}(Component_1.Tag));
+exports.ExtremePointTag = ExtremePointTag;
+exports.default = ExtremePointTag;
+
+},{"../../../Component":291}],389:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    }
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var vd = require("virtual-dom");
+var Component_1 = require("../../../Component");
+var OutlineCreateTag = /** @class */ (function (_super) {
+    __extends(OutlineCreateTag, _super);
+    function OutlineCreateTag(geometry, options, transform, viewportCoords) {
+        var _this = _super.call(this, geometry, transform, viewportCoords) || this;
+        _this._options = { color: options.color == null ? 0xFFFFFF : options.color };
+        _this._createGlObjects();
+        return _this;
+    }
+    OutlineCreateTag.prototype.create = function () {
+        if (this._geometry instanceof Component_1.RectGeometry) {
+            this._created$.next(this);
+        }
+        else if (this._geometry instanceof Component_1.PolygonGeometry) {
+            var polygonGeometry = this._geometry;
+            polygonGeometry.removeVertex2d(polygonGeometry.polygon.length - 2);
+            this._created$.next(this);
+        }
+    };
+    OutlineCreateTag.prototype.dispose = function () {
+        _super.prototype.dispose.call(this);
+        this._disposeLine(this._outline);
+        this._disposeObjects();
+    };
     OutlineCreateTag.prototype.getDOMObjects = function (camera, size) {
         var _this = this;
         var vNodes = [];
@@ -34619,57 +43031,29 @@ var OutlineCreateTag = /** @class */ (function () {
             polygonGeometry.addVertex2d(point);
         }
     };
-    OutlineCreateTag.prototype._canvasToTransform = function (canvas) {
-        var canvasX = Math.round(canvas[0]);
-        var canvasY = Math.round(canvas[1]);
-        var transform = "translate(-50%,-50%) translate(" + canvasX + "px," + canvasY + "px)";
-        return transform;
+    OutlineCreateTag.prototype._onGeometryChanged = function () {
+        this._disposeLine(this._outline);
+        this._disposeObjects();
+        this._createGlObjects();
     };
-    OutlineCreateTag.prototype._colorToBackground = function (color) {
-        return "#" + ("000000" + color.toString(16)).substr(-6);
+    OutlineCreateTag.prototype._disposeObjects = function () {
+        this._outline = null;
+        this._glObjects = [];
     };
-    OutlineCreateTag.prototype._createOutine = function () {
+    OutlineCreateTag.prototype._createGlObjects = function () {
         var polygon3d = this._geometry instanceof Component_1.RectGeometry ?
             this._geometry.getPoints3d(this._transform) :
             this._geometry.getVertices3d(this._transform);
-        var positions = this._getLinePositions(polygon3d);
-        var geometry = new THREE.BufferGeometry();
-        geometry.addAttribute("position", new THREE.BufferAttribute(positions, 3));
-        var material = new THREE.LineBasicMaterial({
-            color: this._options.color,
-            linewidth: 1,
-        });
-        return new THREE.Line(geometry, material);
-    };
-    OutlineCreateTag.prototype._disposeOutline = function () {
-        if (this._outline == null) {
-            return;
-        }
-        var line = this._outline;
-        line.geometry.dispose();
-        line.material.dispose();
-        this._outline = null;
-        this._glObjects = [];
-    };
-    OutlineCreateTag.prototype._getLinePositions = function (polygon3d) {
-        var length = polygon3d.length;
-        var positions = new Float32Array(length * 3);
-        for (var i = 0; i < length; ++i) {
-            var index = 3 * i;
-            var position = polygon3d[i];
-            positions[index] = position[0];
-            positions[index + 1] = position[1];
-            positions[index + 2] = position[2];
-        }
-        return positions;
+        this._outline = this._createOutine(polygon3d, this._options.color);
+        this._glObjects = [this._outline];
     };
     return OutlineCreateTag;
-}());
+}(Component_1.CreateTag));
 exports.OutlineCreateTag = OutlineCreateTag;
 exports.default = OutlineCreateTag;
 
 
-},{"../../../Component":275,"../../../Geo":278,"rxjs":27,"rxjs/operators":225,"three":226,"virtual-dom":231}],366:[function(require,module,exports){
+},{"../../../Component":291,"virtual-dom":247}],390:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -34709,47 +43093,13 @@ var OutlineRenderTag = /** @class */ (function (_super) {
         _this._outline = _this._tag.lineWidth >= 1 ?
             _this._createOutline() :
             null;
-        _this._geometryChangedSubscription = _this._tag.geometry.changed$
-            .subscribe(function () {
-            if (_this._fill != null) {
-                _this._updateFillGeometry();
-            }
-            if (_this._holes.length > 0) {
-                _this._updateHoleGeometries();
-            }
-            if (_this._outline != null) {
-                _this._updateOulineGeometry();
-            }
-        });
-        _this._changedSubscription = _this._tag.changed$
-            .subscribe(function () {
-            var glObjectsChanged = false;
-            if (_this._fill != null) {
-                _this._updateFillMaterial(_this._fill.material);
-            }
-            if (_this._outline == null) {
-                if (_this._tag.lineWidth >= 1) {
-                    _this._holes = _this._createHoles();
-                    _this._outline = _this._createOutline();
-                    glObjectsChanged = true;
-                }
-            }
-            else {
-                _this._updateHoleMaterials();
-                _this._updateOutlineMaterial();
-            }
-            if (glObjectsChanged) {
-                _this._glObjectsChanged$.next(_this);
-            }
-        });
         return _this;
     }
     OutlineRenderTag.prototype.dispose = function () {
+        _super.prototype.dispose.call(this);
         this._disposeFill();
         this._disposeHoles();
         this._disposeOutline();
-        this._changedSubscription.unsubscribe();
-        this._geometryChangedSubscription.unsubscribe();
     };
     OutlineRenderTag.prototype.getDOMObjects = function (atlas, camera, size) {
         var _this = this;
@@ -34765,7 +43115,7 @@ var OutlineRenderTag = /** @class */ (function (_super) {
                 this._tag.geometry.getPoleOfInaccessibility2d(), iconBasicX = _a[0], iconBasicY = _a[1];
             var iconCanvas = this._viewportCoords.basicToCanvasSafe(iconBasicX, iconBasicY, container, this._transform, camera);
             if (iconCanvas != null) {
-                var interact = function (e) {
+                var interact = function () {
                     _this._interact$.next({ offsetX: 0, offsetY: 0, operation: Component_1.TagOperation.None, tag: _this._tag });
                 };
                 if (atlas.loaded) {
@@ -34797,7 +43147,7 @@ var OutlineRenderTag = /** @class */ (function (_super) {
                 var transform = this._tag.geometry instanceof Component_1.RectGeometry ?
                     "translate(" + textCanvasX + "px," + textCanvasY + "px)" :
                     "translate(-50%, -50%) translate(" + textCanvasX + "px," + textCanvasY + "px)";
-                var interact = function (e) {
+                var interact = function () {
                     _this._interact$.next({ offsetX: 0, offsetY: 0, operation: Component_1.TagOperation.None, tag: _this._tag });
                 };
                 var properties = {
@@ -34881,18 +43231,57 @@ var OutlineRenderTag = /** @class */ (function (_super) {
     OutlineRenderTag.prototype.getRetrievableObjects = function () {
         return this._fill != null ? [this._fill] : [];
     };
-    OutlineRenderTag.prototype._colorToCss = function (color) {
-        return "#" + ("000000" + color.toString(16)).substr(-6);
+    OutlineRenderTag.prototype._onGeometryChanged = function () {
+        if (this._fill != null) {
+            this._updateFillGeometry();
+        }
+        if (this._holes.length > 0) {
+            this._updateHoleGeometries();
+        }
+        if (this._outline != null) {
+            this._updateOulineGeometry();
+        }
     };
-    OutlineRenderTag.prototype._createFill = function () {
-        var triangles = this._getTriangles();
-        var positions = new Float32Array(triangles);
-        var geometry = new THREE.BufferGeometry();
-        geometry.addAttribute("position", new THREE.BufferAttribute(positions, 3));
-        geometry.computeBoundingSphere();
-        var material = new THREE.MeshBasicMaterial({ side: THREE.DoubleSide, transparent: true });
-        this._updateFillMaterial(material);
-        return new THREE.Mesh(geometry, material);
+    OutlineRenderTag.prototype._onTagChanged = function () {
+        var glObjectsChanged = false;
+        if (this._fill != null) {
+            this._updateFillMaterial(this._fill.material);
+        }
+        if (this._outline == null) {
+            if (this._tag.lineWidth >= 1) {
+                this._holes = this._createHoles();
+                this._outline = this._createOutline();
+                glObjectsChanged = true;
+            }
+        }
+        else {
+            this._updateHoleMaterials();
+            this._updateOutlineMaterial();
+        }
+        return glObjectsChanged;
+    };
+    OutlineRenderTag.prototype._getPoints3d = function () {
+        return this._in3dDomain() ?
+            this._tag.geometry.getVertices3d(this._transform) :
+            this._tag.geometry.getPoints3d(this._transform);
+    };
+    OutlineRenderTag.prototype._getTriangles = function () {
+        return this._in3dDomain() ?
+            this._tag.geometry.get3dDomainTriangles3d(this._transform) :
+            this._tag.geometry.getTriangles3d(this._transform);
+    };
+    OutlineRenderTag.prototype._updateFillMaterial = function (material) {
+        material.color = new THREE.Color(this._tag.fillColor);
+        material.opacity = this._tag.fillOpacity;
+        material.needsUpdate = true;
+    };
+    OutlineRenderTag.prototype._updateLineBasicMaterial = function (material) {
+        material.color = new THREE.Color(this._tag.lineColor);
+        material.linewidth = Math.max(this._tag.lineWidth, 1);
+        material.visible = this._tag.lineWidth >= 1 && this._tag.lineOpacity > 0;
+        material.opacity = this._tag.lineOpacity;
+        material.transparent = this._tag.lineOpacity < 1;
+        material.needsUpdate = true;
     };
     OutlineRenderTag.prototype._createHoles = function () {
         var holes = [];
@@ -34906,7 +43295,101 @@ var OutlineRenderTag = /** @class */ (function (_super) {
         }
         return holes;
     };
-    OutlineRenderTag.prototype._createLine = function (points3d) {
+    OutlineRenderTag.prototype._disposeHoles = function () {
+        for (var _i = 0, _a = this._holes; _i < _a.length; _i++) {
+            var hole = _a[_i];
+            hole.geometry.dispose();
+            hole.material.dispose();
+        }
+        this._holes = [];
+    };
+    OutlineRenderTag.prototype._getHoles3d = function () {
+        var polygonGeometry = this._tag.geometry;
+        return this._in3dDomain() ?
+            polygonGeometry.getHoleVertices3d(this._transform) :
+            polygonGeometry.getHolePoints3d(this._transform);
+    };
+    OutlineRenderTag.prototype._in3dDomain = function () {
+        return this._tag.geometry instanceof Component_1.PolygonGeometry && this._tag.domain === Component_1.TagDomain.ThreeDimensional;
+    };
+    OutlineRenderTag.prototype._updateHoleGeometries = function () {
+        var holes3d = this._getHoles3d();
+        if (holes3d.length !== this._holes.length) {
+            throw new Error("Changing the number of holes is not supported.");
+        }
+        for (var i = 0; i < this._holes.length; i++) {
+            var holePoints3d = holes3d[i];
+            var hole = this._holes[i];
+            this._updateLine(hole, holePoints3d);
+        }
+    };
+    OutlineRenderTag.prototype._updateHoleMaterials = function () {
+        for (var _i = 0, _a = this._holes; _i < _a.length; _i++) {
+            var hole = _a[_i];
+            this._updateLineBasicMaterial(hole.material);
+        }
+    };
+    OutlineRenderTag.prototype._updateOutlineMaterial = function () {
+        this._updateLineBasicMaterial(this._outline.material);
+    };
+    return OutlineRenderTag;
+}(Component_1.OutlineRenderTagBase));
+exports.OutlineRenderTag = OutlineRenderTag;
+
+
+},{"../../../Component":291,"three":242,"virtual-dom":247}],391:[function(require,module,exports){
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    }
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var THREE = require("three");
+var Component_1 = require("../../../Component");
+var OutlineRenderTagBase = /** @class */ (function (_super) {
+    __extends(OutlineRenderTagBase, _super);
+    function OutlineRenderTagBase(tag, transform) {
+        var _this = _super.call(this, tag, transform) || this;
+        _this._geometryChangedSubscription = _this._tag.geometry.changed$
+            .subscribe(function () {
+            _this._onGeometryChanged();
+        });
+        _this._changedSubscription = _this._tag.changed$
+            .subscribe(function () {
+            var glObjectsChanged = _this._onTagChanged();
+            if (glObjectsChanged) {
+                _this._glObjectsChanged$.next(_this);
+            }
+        });
+        return _this;
+    }
+    OutlineRenderTagBase.prototype.dispose = function () {
+        this._changedSubscription.unsubscribe();
+        this._geometryChangedSubscription.unsubscribe();
+    };
+    OutlineRenderTagBase.prototype._colorToCss = function (color) {
+        return "#" + ("000000" + color.toString(16)).substr(-6);
+    };
+    OutlineRenderTagBase.prototype._createFill = function () {
+        var triangles = this._getTriangles();
+        var positions = new Float32Array(triangles);
+        var geometry = new THREE.BufferGeometry();
+        geometry.addAttribute("position", new THREE.BufferAttribute(positions, 3));
+        geometry.computeBoundingSphere();
+        var material = new THREE.MeshBasicMaterial({ side: THREE.DoubleSide, transparent: true });
+        this._updateFillMaterial(material);
+        return new THREE.Mesh(geometry, material);
+    };
+    OutlineRenderTagBase.prototype._createLine = function (points3d) {
         var positions = this._getLinePositions(points3d);
         var geometry = new THREE.BufferGeometry();
         geometry.addAttribute("position", new THREE.BufferAttribute(positions, 3));
@@ -34917,10 +43400,10 @@ var OutlineRenderTag = /** @class */ (function (_super) {
         line.renderOrder = 1;
         return line;
     };
-    OutlineRenderTag.prototype._createOutline = function () {
+    OutlineRenderTagBase.prototype._createOutline = function () {
         return this._createLine(this._getPoints3d());
     };
-    OutlineRenderTag.prototype._disposeFill = function () {
+    OutlineRenderTagBase.prototype._disposeFill = function () {
         if (this._fill == null) {
             return;
         }
@@ -34928,15 +43411,7 @@ var OutlineRenderTag = /** @class */ (function (_super) {
         this._fill.material.dispose();
         this._fill = null;
     };
-    OutlineRenderTag.prototype._disposeHoles = function () {
-        for (var _i = 0, _a = this._holes; _i < _a.length; _i++) {
-            var hole = _a[_i];
-            hole.geometry.dispose();
-            hole.material.dispose();
-        }
-        this._holes = [];
-    };
-    OutlineRenderTag.prototype._disposeOutline = function () {
+    OutlineRenderTagBase.prototype._disposeOutline = function () {
         if (this._outline == null) {
             return;
         }
@@ -34944,7 +43419,7 @@ var OutlineRenderTag = /** @class */ (function (_super) {
         this._outline.material.dispose();
         this._outline = null;
     };
-    OutlineRenderTag.prototype._getLinePositions = function (points3d) {
+    OutlineRenderTagBase.prototype._getLinePositions = function (points3d) {
         var length = points3d.length;
         var positions = new Float32Array(length * 3);
         for (var i = 0; i < length; ++i) {
@@ -34956,26 +43431,7 @@ var OutlineRenderTag = /** @class */ (function (_super) {
         }
         return positions;
     };
-    OutlineRenderTag.prototype._getHoles3d = function () {
-        var polygonGeometry = this._tag.geometry;
-        return this._in3dDomain() ?
-            polygonGeometry.getHoleVertices3d(this._transform) :
-            polygonGeometry.getHolePoints3d(this._transform);
-    };
-    OutlineRenderTag.prototype._getPoints3d = function () {
-        return this._in3dDomain() ?
-            this._tag.geometry.getVertices3d(this._transform) :
-            this._tag.geometry.getPoints3d(this._transform);
-    };
-    OutlineRenderTag.prototype._getTriangles = function () {
-        return this._in3dDomain() ?
-            this._tag.geometry.get3dDomainTriangles3d(this._transform) :
-            this._tag.geometry.getTriangles3d(this._transform);
-    };
-    OutlineRenderTag.prototype._in3dDomain = function () {
-        return this._tag.geometry instanceof Component_1.PolygonGeometry && this._tag.domain === Component_1.TagDomain.ThreeDimensional;
-    };
-    OutlineRenderTag.prototype._interact = function (operation, cursor, vertexIndex) {
+    OutlineRenderTagBase.prototype._interact = function (operation, cursor, vertexIndex) {
         var _this = this;
         return function (e) {
             var offsetX = e.offsetX - e.target.offsetWidth / 2;
@@ -34990,7 +43446,7 @@ var OutlineRenderTag = /** @class */ (function (_super) {
             });
         };
     };
-    OutlineRenderTag.prototype._updateFillGeometry = function () {
+    OutlineRenderTagBase.prototype._updateFillGeometry = function () {
         var triangles = this._getTriangles();
         var positions = new Float32Array(triangles);
         var geometry = this._fill.geometry;
@@ -35005,30 +43461,7 @@ var OutlineRenderTag = /** @class */ (function (_super) {
         }
         geometry.computeBoundingSphere();
     };
-    OutlineRenderTag.prototype._updateFillMaterial = function (material) {
-        material.color = new THREE.Color(this._tag.fillColor);
-        material.opacity = this._tag.fillOpacity;
-        material.needsUpdate = true;
-    };
-    OutlineRenderTag.prototype._updateHoleGeometries = function () {
-        var holes3d = this._getHoles3d();
-        if (holes3d.length !== this._holes.length) {
-            throw new Error("Changing the number of holes is not supported.");
-        }
-        for (var i = 0; i < this._holes.length; i++) {
-            var holePoints3d = holes3d[i];
-            var hole = this._holes[i];
-            this._updateLine(hole, holePoints3d);
-        }
-    };
-    OutlineRenderTag.prototype._updateHoleMaterials = function () {
-        for (var _i = 0, _a = this._holes; _i < _a.length; _i++) {
-            var hole = _a[_i];
-            var material = hole.material;
-            this._updateLineBasicMaterial(material);
-        }
-    };
-    OutlineRenderTag.prototype._updateLine = function (line, points3d) {
+    OutlineRenderTagBase.prototype._updateLine = function (line, points3d) {
         var positions = this._getLinePositions(points3d);
         var geometry = line.geometry;
         var attribute = geometry.getAttribute("position");
@@ -35036,27 +43469,16 @@ var OutlineRenderTag = /** @class */ (function (_super) {
         attribute.needsUpdate = true;
         geometry.computeBoundingSphere();
     };
-    OutlineRenderTag.prototype._updateOulineGeometry = function () {
+    OutlineRenderTagBase.prototype._updateOulineGeometry = function () {
         this._updateLine(this._outline, this._getPoints3d());
     };
-    OutlineRenderTag.prototype._updateOutlineMaterial = function () {
-        var material = this._outline.material;
-        this._updateLineBasicMaterial(material);
-    };
-    OutlineRenderTag.prototype._updateLineBasicMaterial = function (material) {
-        material.color = new THREE.Color(this._tag.lineColor);
-        material.linewidth = Math.max(this._tag.lineWidth, 1);
-        material.visible = this._tag.lineWidth >= 1 && this._tag.lineOpacity > 0;
-        material.opacity = this._tag.lineOpacity;
-        material.transparent = this._tag.lineOpacity < 1;
-        material.needsUpdate = true;
-    };
-    return OutlineRenderTag;
+    return OutlineRenderTagBase;
 }(Component_1.RenderTag));
-exports.OutlineRenderTag = OutlineRenderTag;
+exports.OutlineRenderTagBase = OutlineRenderTagBase;
+exports.default = OutlineRenderTagBase;
 
 
-},{"../../../Component":275,"three":226,"virtual-dom":231}],367:[function(require,module,exports){
+},{"../../../Component":291,"three":242}],392:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -35462,7 +43884,7 @@ var OutlineTag = /** @class */ (function (_super) {
 exports.OutlineTag = OutlineTag;
 exports.default = OutlineTag;
 
-},{"../../../Component":275,"../../../Viewer":286,"rxjs":27}],368:[function(require,module,exports){
+},{"../../../Component":291,"../../../Viewer":302,"rxjs":43}],393:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -35501,7 +43923,7 @@ var RenderTag = /** @class */ (function () {
 exports.RenderTag = RenderTag;
 exports.default = RenderTag;
 
-},{"../../../Geo":278,"rxjs":27}],369:[function(require,module,exports){
+},{"../../../Geo":294,"rxjs":43}],394:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -35619,7 +44041,7 @@ var SpotRenderTag = /** @class */ (function (_super) {
 exports.SpotRenderTag = SpotRenderTag;
 
 
-},{"../../../Component":275,"../../../Viewer":286,"virtual-dom":231}],370:[function(require,module,exports){
+},{"../../../Component":291,"../../../Viewer":302,"virtual-dom":247}],395:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -35802,7 +44224,7 @@ var SpotTag = /** @class */ (function (_super) {
 exports.SpotTag = SpotTag;
 exports.default = SpotTag;
 
-},{"../../../Component":275}],371:[function(require,module,exports){
+},{"../../../Component":291}],396:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -35919,7 +44341,7 @@ var Tag = /** @class */ (function (_super) {
 exports.Tag = Tag;
 exports.default = Tag;
 
-},{"../../../Utils":285,"rxjs":27,"rxjs/operators":225}],372:[function(require,module,exports){
+},{"../../../Utils":301,"rxjs":43,"rxjs/operators":241}],397:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -35951,7 +44373,37 @@ var TagDomain;
 })(TagDomain = exports.TagDomain || (exports.TagDomain = {}));
 exports.default = TagDomain;
 
-},{}],373:[function(require,module,exports){
+},{}],398:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+/**
+ * Enumeration for component size.
+ * @enum {number}
+ * @readonly
+ * @description May be used by a component to allow for resizing
+ * of the UI elements rendered by the component.
+ */
+var ComponentSize;
+(function (ComponentSize) {
+    /**
+     * Automatic size. The size of the elements will automatically
+     * change at a predefined threshold.
+     */
+    ComponentSize[ComponentSize["Automatic"] = 0] = "Automatic";
+    /**
+     * Large size. The size of the elements will be fixed until another
+     * component size is configured.
+     */
+    ComponentSize[ComponentSize["Large"] = 1] = "Large";
+    /**
+     * Small size. The size of the elements will be fixed until another
+     * component size is configured.
+     */
+    ComponentSize[ComponentSize["Small"] = 2] = "Small";
+})(ComponentSize = exports.ComponentSize || (exports.ComponentSize = {}));
+exports.default = ComponentSize;
+
+},{}],399:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var HandlerBase = /** @class */ (function () {
@@ -36007,7 +44459,7 @@ var HandlerBase = /** @class */ (function () {
 exports.HandlerBase = HandlerBase;
 exports.default = HandlerBase;
 
-},{}],374:[function(require,module,exports){
+},{}],400:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
@@ -36651,49 +45103,118 @@ var MeshFactory = /** @class */ (function () {
 exports.MeshFactory = MeshFactory;
 exports.default = MeshFactory;
 
-},{"../../Component":275,"three":226}],375:[function(require,module,exports){
+},{"../../Component":291,"three":242}],401:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
 var MeshScene = /** @class */ (function () {
     function MeshScene() {
-        this.scene = new THREE.Scene();
-        this.sceneOld = new THREE.Scene();
-        this.imagePlanes = [];
-        this.imagePlanesOld = [];
+        this._planes = {};
+        this._planesOld = {};
+        this._planesPeriphery = {};
+        this._scene = new THREE.Scene();
+        this._sceneOld = new THREE.Scene();
+        this._scenePeriphery = new THREE.Scene();
     }
+    Object.defineProperty(MeshScene.prototype, "planes", {
+        get: function () {
+            return this._planes;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(MeshScene.prototype, "planesOld", {
+        get: function () {
+            return this._planesOld;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(MeshScene.prototype, "planesPeriphery", {
+        get: function () {
+            return this._planesPeriphery;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(MeshScene.prototype, "scene", {
+        get: function () {
+            return this._scene;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(MeshScene.prototype, "sceneOld", {
+        get: function () {
+            return this._sceneOld;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(MeshScene.prototype, "scenePeriphery", {
+        get: function () {
+            return this._scenePeriphery;
+        },
+        enumerable: true,
+        configurable: true
+    });
     MeshScene.prototype.updateImagePlanes = function (planes) {
-        this._dispose(this.imagePlanesOld, this.sceneOld);
-        for (var _i = 0, _a = this.imagePlanes; _i < _a.length; _i++) {
-            var plane = _a[_i];
-            this.scene.remove(plane);
-            this.sceneOld.add(plane);
+        this._dispose(this._planesOld, this.sceneOld);
+        for (var key in this._planes) {
+            if (!this._planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = this._planes[key];
+            this._scene.remove(plane);
+            this._sceneOld.add(plane);
         }
-        for (var _b = 0, planes_1 = planes; _b < planes_1.length; _b++) {
-            var plane = planes_1[_b];
-            this.scene.add(plane);
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            this._scene.add(planes[key]);
         }
-        this.imagePlanesOld = this.imagePlanes;
-        this.imagePlanes = planes;
+        this._planesOld = this._planes;
+        this._planes = planes;
     };
     MeshScene.prototype.addImagePlanes = function (planes) {
-        for (var _i = 0, planes_2 = planes; _i < planes_2.length; _i++) {
-            var plane = planes_2[_i];
-            this.scene.add(plane);
-            this.imagePlanes.push(plane);
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
+            this._scene.add(plane);
+            this._planes[key] = plane;
         }
     };
     MeshScene.prototype.addImagePlanesOld = function (planes) {
-        for (var _i = 0, planes_3 = planes; _i < planes_3.length; _i++) {
-            var plane = planes_3[_i];
-            this.sceneOld.add(plane);
-            this.imagePlanesOld.push(plane);
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
+            this._sceneOld.add(plane);
+            this._planesOld[key] = plane;
         }
     };
     MeshScene.prototype.setImagePlanes = function (planes) {
         this._clear();
         this.addImagePlanes(planes);
     };
+    MeshScene.prototype.addPeripheryPlanes = function (planes) {
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
+            this._scenePeriphery.add(plane);
+            this._planesPeriphery[key] = plane;
+        }
+    };
+    MeshScene.prototype.setPeripheryPlanes = function (planes) {
+        this._clearPeriphery();
+        this.addPeripheryPlanes(planes);
+    };
     MeshScene.prototype.setImagePlanesOld = function (planes) {
         this._clearOld();
         this.addImagePlanesOld(planes);
@@ -36703,16 +45224,23 @@ var MeshScene = /** @class */ (function () {
         this._clearOld();
     };
     MeshScene.prototype._clear = function () {
-        this._dispose(this.imagePlanes, this.scene);
-        this.imagePlanes.length = 0;
+        this._dispose(this._planes, this._scene);
+        this._planes = {};
     };
     MeshScene.prototype._clearOld = function () {
-        this._dispose(this.imagePlanesOld, this.sceneOld);
-        this.imagePlanesOld.length = 0;
+        this._dispose(this._planesOld, this._sceneOld);
+        this._planesOld = {};
+    };
+    MeshScene.prototype._clearPeriphery = function () {
+        this._dispose(this._planesPeriphery, this._scenePeriphery);
+        this._planesPeriphery = {};
     };
     MeshScene.prototype._dispose = function (planes, scene) {
-        for (var _i = 0, planes_4 = planes; _i < planes_4.length; _i++) {
-            var plane = planes_4[_i];
+        for (var key in planes) {
+            if (!planes.hasOwnProperty(key)) {
+                continue;
+            }
+            var plane = planes[key];
             scene.remove(plane);
             plane.geometry.dispose();
             plane.material.dispose();
@@ -36727,7 +45255,7 @@ var MeshScene = /** @class */ (function () {
 exports.MeshScene = MeshScene;
 exports.default = MeshScene;
 
-},{"three":226}],376:[function(require,module,exports){
+},{"three":242}],402:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -36756,7 +45284,7 @@ var MouseOperator = /** @class */ (function () {
 exports.MouseOperator = MouseOperator;
 exports.default = MouseOperator;
 
-},{"rxjs":27,"rxjs/operators":225}],377:[function(require,module,exports){
+},{"rxjs":43,"rxjs/operators":241}],403:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -36778,6 +45306,23 @@ var vd = require("virtual-dom");
 var Component_1 = require("../../Component");
 var Geo_1 = require("../../Geo");
 var State_1 = require("../../State");
+var ComponentSize_1 = require("../utils/ComponentSize");
+/**
+ * @class ZoomComponent
+ *
+ * @classdesc Component rendering UI elements used for zooming.
+ *
+ * @example
+ * ```
+ * var viewer = new Mapillary.Viewer(
+ *     "<element-id>",
+ *     "<client-id>",
+ *     "<my key>");
+ *
+ * var zoomComponent = viewer.getComponent("zoom");
+ * zoomComponent.configure({ size: Mapillary.ComponentSize.Small });
+ * ```
+ */
 var ZoomComponent = /** @class */ (function (_super) {
     __extends(ZoomComponent, _super);
     function ZoomComponent(name, container, navigator) {
@@ -36788,11 +45333,9 @@ var ZoomComponent = /** @class */ (function (_super) {
     }
     ZoomComponent.prototype._activate = function () {
         var _this = this;
-        this._renderSubscription = rxjs_1.combineLatest(this._navigator.stateService.currentState$, this._navigator.stateService.state$).pipe(operators_1.map(function (_a) {
-            var frame = _a[0], state = _a[1];
-            return [frame.state.zoom, state];
-        }), operators_1.map(function (_a) {
-            var zoom = _a[0], state = _a[1];
+        this._renderSubscription = rxjs_1.combineLatest(this._navigator.stateService.currentState$, this._navigator.stateService.state$, this._configuration$, this._container.renderService.size$).pipe(operators_1.map(function (_a) {
+            var frame = _a[0], state = _a[1], configuration = _a[2], size = _a[3];
+            var zoom = frame.state.zoom;
             var zoomInIcon = vd.h("div.ZoomInIcon", []);
             var zoomInButton = zoom >= 3 || state === State_1.State.Waiting ?
                 vd.h("div.ZoomInButtonDisabled", [zoomInIcon]) :
@@ -36801,9 +45344,12 @@ var ZoomComponent = /** @class */ (function (_super) {
             var zoomOutButton = zoom <= 0 || state === State_1.State.Waiting ?
                 vd.h("div.ZoomOutButtonDisabled", [zoomOutIcon]) :
                 vd.h("div.ZoomOutButton", { onclick: function () { _this._zoomDelta$.next(-1); } }, [zoomOutIcon]);
+            var compact = configuration.size === ComponentSize_1.default.Small ||
+                configuration.size === ComponentSize_1.default.Automatic && size.width < 640 ?
+                ".ZoomCompact" : "";
             return {
                 name: _this._name,
-                vnode: vd.h("div.ZoomContainer", { oncontextmenu: function (event) { event.preventDefault(); } }, [zoomInButton, zoomOutButton]),
+                vnode: vd.h("div.ZoomContainer" + compact, { oncontextmenu: function (event) { event.preventDefault(); } }, [zoomInButton, zoomOutButton]),
             };
         }))
             .subscribe(this._container.domRenderer.render$);
@@ -36820,7 +45366,7 @@ var ZoomComponent = /** @class */ (function (_super) {
         this._zoomSubscription.unsubscribe();
     };
     ZoomComponent.prototype._getDefaultConfiguration = function () {
-        return {};
+        return { size: ComponentSize_1.default.Automatic };
     };
     ZoomComponent.componentName = "zoom";
     return ZoomComponent;
@@ -36829,7 +45375,7 @@ exports.ZoomComponent = ZoomComponent;
 Component_1.ComponentService.register(ZoomComponent);
 exports.default = ZoomComponent;
 
-},{"../../Component":275,"../../Geo":278,"../../State":282,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],378:[function(require,module,exports){
+},{"../../Component":291,"../../Geo":294,"../../State":298,"../utils/ComponentSize":398,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],404:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -36865,7 +45411,7 @@ var AbortMapillaryError = /** @class */ (function (_super) {
 exports.AbortMapillaryError = AbortMapillaryError;
 exports.default = AbortMapillaryError;
 
-},{"./MapillaryError":381}],379:[function(require,module,exports){
+},{"./MapillaryError":407}],405:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -36895,7 +45441,7 @@ var ArgumentMapillaryError = /** @class */ (function (_super) {
 exports.ArgumentMapillaryError = ArgumentMapillaryError;
 exports.default = ArgumentMapillaryError;
 
-},{"./MapillaryError":381}],380:[function(require,module,exports){
+},{"./MapillaryError":407}],406:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -36925,7 +45471,7 @@ var GraphMapillaryError = /** @class */ (function (_super) {
 exports.GraphMapillaryError = GraphMapillaryError;
 exports.default = GraphMapillaryError;
 
-},{"./MapillaryError":381}],381:[function(require,module,exports){
+},{"./MapillaryError":407}],407:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -36954,7 +45500,7 @@ var MapillaryError = /** @class */ (function (_super) {
 exports.MapillaryError = MapillaryError;
 exports.default = MapillaryError;
 
-},{}],382:[function(require,module,exports){
+},{}],408:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
@@ -37103,9 +45649,10 @@ var Camera = /** @class */ (function () {
 }());
 exports.Camera = Camera;
 
-},{"three":226}],383:[function(require,module,exports){
+},{"three":242}],409:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
+var THREE = require("three");
 var Geo_1 = require("../Geo");
 var geoCoords = new Geo_1.GeoCoords();
 var spatial = new Geo_1.Spatial();
@@ -37116,8 +45663,36 @@ function computeTranslation(position, rotation, reference) {
     return translation;
 }
 exports.computeTranslation = computeTranslation;
+function computeProjectedPoints(transform, basicVertices, basicDirections, pointsPerLine, viewportCoords) {
+    var basicPoints = [];
+    for (var side = 0; side < basicVertices.length; ++side) {
+        var v = basicVertices[side];
+        var d = basicDirections[side];
+        for (var i = 0; i <= pointsPerLine; ++i) {
+            basicPoints.push([v[0] + d[0] * i / pointsPerLine,
+                v[1] + d[1] * i / pointsPerLine]);
+        }
+    }
+    var camera = new THREE.Camera();
+    camera.up.copy(transform.upVector());
+    camera.position.copy(new THREE.Vector3().fromArray(transform.unprojectSfM([0, 0], 0)));
+    camera.lookAt(new THREE.Vector3().fromArray(transform.unprojectSfM([0, 0], 10)));
+    camera.updateMatrix();
+    camera.updateMatrixWorld(true);
+    var projectedPoints = basicPoints
+        .map(function (basicPoint) {
+        var worldPoint = transform.unprojectBasic(basicPoint, 10000);
+        var cameraPoint = viewportCoords.worldToCamera(worldPoint, camera);
+        return [
+            Math.abs(cameraPoint[0] / cameraPoint[2]),
+            Math.abs(cameraPoint[1] / cameraPoint[2]),
+        ];
+    });
+    return projectedPoints;
+}
+exports.computeProjectedPoints = computeProjectedPoints;
 
-},{"../Geo":278}],384:[function(require,module,exports){
+},{"../Geo":294,"three":242}],410:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -37341,7 +45916,7 @@ var GeoCoords = /** @class */ (function () {
 exports.GeoCoords = GeoCoords;
 exports.default = GeoCoords;
 
-},{}],385:[function(require,module,exports){
+},{}],411:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function sign(n) {
@@ -37414,7 +45989,7 @@ function segmentIntersection(s1, s2) {
 }
 exports.segmentIntersection = segmentIntersection;
 
-},{}],386:[function(require,module,exports){
+},{}],412:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
@@ -37617,6 +46192,13 @@ var Spatial = /** @class */ (function () {
         var projection = v.dot(new THREE.Vector3().fromArray(planeNormal));
         return Math.asin(projection / norm);
     };
+    Spatial.prototype.azimuthal = function (direction, up) {
+        var directionVector = new THREE.Vector3().fromArray(direction);
+        var upVector = new THREE.Vector3().fromArray(up);
+        var upProjection = directionVector.clone().dot(upVector);
+        var planeProjection = directionVector.clone().sub(upVector.clone().multiplyScalar(upProjection));
+        return Math.atan2(planeProjection.y, planeProjection.x);
+    };
     /**
      * Calculates the distance between two coordinates
      * (latitude longitude pairs) in meters according to
@@ -37643,7 +46225,7 @@ var Spatial = /** @class */ (function () {
 exports.Spatial = Spatial;
 exports.default = Spatial;
 
-},{"three":226}],387:[function(require,module,exports){
+},{"three":242}],413:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
@@ -38334,7 +46916,7 @@ var Transform = /** @class */ (function () {
 }());
 exports.Transform = Transform;
 
-},{"three":226}],388:[function(require,module,exports){
+},{"three":242}],414:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
@@ -38638,6 +47220,24 @@ var ViewportCoords = /** @class */ (function () {
         var canvas = this.viewportToCanvas(viewport[0], viewport[1], container);
         return canvas;
     };
+    /**
+     * Project 3D world coordinates to canvas coordinates safely. If 3D
+     * point is behind camera null will be returned.
+     *
+     * @param {Array<number>} point3D - 3D world coordinates.
+     * @param {HTMLElement} container - The viewer container.
+     * @param {THREE.Camera} camera - Camera used in rendering.
+     * @returns {Array<number>} 2D canvas coordinates.
+     */
+    ViewportCoords.prototype.projectToCanvasSafe = function (point3d, container, camera) {
+        var pointCamera = this.worldToCamera(point3d, camera);
+        if (pointCamera[2] > 0) {
+            return null;
+        }
+        var viewport = this.projectToViewport(point3d, camera);
+        var canvas = this.viewportToCanvas(viewport[0], viewport[1], container);
+        return canvas;
+    };
     /**
      * Project 3D world coordinates to viewport coordinates.
      *
@@ -38728,7 +47328,7 @@ exports.ViewportCoords = ViewportCoords;
 exports.default = ViewportCoords;
 
 
-},{"three":226}],389:[function(require,module,exports){
+},{"three":242}],415:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -38816,7 +47416,7 @@ var FilterCreator = /** @class */ (function () {
 exports.FilterCreator = FilterCreator;
 exports.default = FilterCreator;
 
-},{}],390:[function(require,module,exports){
+},{}],416:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -40027,7 +48627,7 @@ var Graph = /** @class */ (function () {
 exports.Graph = Graph;
 exports.default = Graph;
 
-},{"../Edge":276,"../Error":277,"../Graph":279,"rbush":26,"rxjs":27,"rxjs/operators":225}],391:[function(require,module,exports){
+},{"../Edge":292,"../Error":293,"../Graph":295,"rbush":42,"rxjs":43,"rxjs/operators":241}],417:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var geohash = require("latlon-geohash");
@@ -40202,7 +48802,7 @@ var GraphCalculator = /** @class */ (function () {
 exports.GraphCalculator = GraphCalculator;
 exports.default = GraphCalculator;
 
-},{"../Error":277,"../Geo":278,"latlon-geohash":21,"three":226}],392:[function(require,module,exports){
+},{"../Error":293,"../Geo":294,"latlon-geohash":21,"three":242}],418:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -40234,7 +48834,7 @@ var GraphMode;
 })(GraphMode = exports.GraphMode || (exports.GraphMode = {}));
 exports.default = GraphMode;
 
-},{}],393:[function(require,module,exports){
+},{}],419:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -40594,7 +49194,7 @@ var GraphService = /** @class */ (function () {
 exports.GraphService = GraphService;
 exports.default = GraphService;
 
-},{"../Graph":279,"rxjs":27,"rxjs/operators":225}],394:[function(require,module,exports){
+},{"../Graph":295,"rxjs":43,"rxjs/operators":241}],420:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
@@ -40643,7 +49243,7 @@ var ImageLoadingService = /** @class */ (function () {
 }());
 exports.ImageLoadingService = ImageLoadingService;
 
-},{"rxjs":27,"rxjs/operators":225}],395:[function(require,module,exports){
+},{"rxjs":43,"rxjs/operators":241}],421:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Pbf = require("pbf");
@@ -40666,7 +49266,7 @@ var MeshReader = /** @class */ (function () {
 }());
 exports.MeshReader = MeshReader;
 
-},{"pbf":24}],396:[function(require,module,exports){
+},{"pbf":40}],422:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
@@ -40811,6 +49411,19 @@ var Node = /** @class */ (function () {
         enumerable: true,
         configurable: true
     });
+    Object.defineProperty(Node.prototype, "clusterKey", {
+        /**
+         * Get clusterKey.
+         *
+         * @returns {string} Unique key of the SfM cluster to which
+         * the node belongs.
+         */
+        get: function () {
+            return this._fill.cluster_key;
+        },
+        enumerable: true,
+        configurable: true
+    });
     Object.defineProperty(Node.prototype, "ck1", {
         /**
          * Get ck1.
@@ -41011,6 +49624,8 @@ var Node = /** @class */ (function () {
          *
          * @returns {ILoadStatus} Value indicating the load status
          * of the mesh and image.
+         *
+         * @ignore
          */
         get: function () {
             return this._cache.loadStatus;
@@ -41222,6 +49837,8 @@ var Node = /** @class */ (function () {
          *
          * @returns {IEdgeStatus} Value describing the status of the
          * sequence edges.
+         *
+         * @ignore
          */
         get: function () {
             return this._cache.sequenceEdges;
@@ -41252,6 +49869,8 @@ var Node = /** @class */ (function () {
          *
          * @returns {IEdgeStatus} Value describing the status of the
          * spatial edges.
+         *
+         * @ignore
          */
         get: function () {
             return this._cache.spatialEdges;
@@ -41451,7 +50070,7 @@ var Node = /** @class */ (function () {
 exports.Node = Node;
 exports.default = Node;
 
-},{"rxjs/operators":225}],397:[function(require,module,exports){
+},{"rxjs/operators":241}],423:[function(require,module,exports){
 (function (Buffer){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
@@ -41873,7 +50492,7 @@ exports.default = NodeCache;
 
 }).call(this,require("buffer").Buffer)
 
-},{"../Graph":279,"../Utils":285,"buffer":7,"rxjs":27,"rxjs/operators":225}],398:[function(require,module,exports){
+},{"../Graph":295,"../Utils":301,"buffer":7,"rxjs":43,"rxjs/operators":241}],424:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -41961,7 +50580,7 @@ var Sequence = /** @class */ (function () {
 exports.Sequence = Sequence;
 exports.default = Sequence;
 
-},{}],399:[function(require,module,exports){
+},{}],425:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
@@ -42562,7 +51181,7 @@ var EdgeCalculator = /** @class */ (function () {
 exports.EdgeCalculator = EdgeCalculator;
 exports.default = EdgeCalculator;
 
-},{"../../Edge":276,"../../Error":277,"../../Geo":278,"three":226}],400:[function(require,module,exports){
+},{"../../Edge":292,"../../Error":293,"../../Geo":294,"three":242}],426:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var EdgeCalculatorCoefficients = /** @class */ (function () {
@@ -42588,7 +51207,7 @@ var EdgeCalculatorCoefficients = /** @class */ (function () {
 exports.EdgeCalculatorCoefficients = EdgeCalculatorCoefficients;
 exports.default = EdgeCalculatorCoefficients;
 
-},{}],401:[function(require,module,exports){
+},{}],427:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Edge_1 = require("../../Edge");
@@ -42661,7 +51280,7 @@ var EdgeCalculatorDirections = /** @class */ (function () {
 }());
 exports.EdgeCalculatorDirections = EdgeCalculatorDirections;
 
-},{"../../Edge":276}],402:[function(require,module,exports){
+},{"../../Edge":292}],428:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var EdgeCalculatorSettings = /** @class */ (function () {
@@ -42698,7 +51317,7 @@ var EdgeCalculatorSettings = /** @class */ (function () {
 exports.EdgeCalculatorSettings = EdgeCalculatorSettings;
 exports.default = EdgeCalculatorSettings;
 
-},{}],403:[function(require,module,exports){
+},{}],429:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -42756,7 +51375,7 @@ var EdgeDirection;
     EdgeDirection[EdgeDirection["Similar"] = 10] = "Similar";
 })(EdgeDirection = exports.EdgeDirection || (exports.EdgeDirection = {}));
 
-},{}],404:[function(require,module,exports){
+},{}],430:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -42933,7 +51552,7 @@ exports.DOMRenderer = DOMRenderer;
 exports.default = DOMRenderer;
 
 
-},{"../Render":281,"rxjs":27,"rxjs/operators":225,"virtual-dom":231}],405:[function(require,module,exports){
+},{"../Render":297,"rxjs":43,"rxjs/operators":241,"virtual-dom":247}],431:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var GLRenderStage;
@@ -42943,7 +51562,7 @@ var GLRenderStage;
 })(GLRenderStage = exports.GLRenderStage || (exports.GLRenderStage = {}));
 exports.default = GLRenderStage;
 
-},{}],406:[function(require,module,exports){
+},{}],432:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -43159,7 +51778,7 @@ exports.GLRenderer = GLRenderer;
 exports.default = GLRenderer;
 
 
-},{"../Render":281,"../Utils":285,"rxjs":27,"rxjs/operators":225,"three":226}],407:[function(require,module,exports){
+},{"../Render":297,"../Utils":301,"rxjs":43,"rxjs/operators":241,"three":242}],433:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
@@ -43247,6 +51866,20 @@ var RenderCamera = /** @class */ (function () {
         enumerable: true,
         configurable: true
     });
+    RenderCamera.prototype.getTilt = function () {
+        return 90 - this._spatial.radToDeg(this._rotation.theta);
+    };
+    RenderCamera.prototype.fovToZoom = function (fov) {
+        fov = Math.min(90, Math.max(0, fov));
+        var currentFov = this._computeCurrentFov(0);
+        var actualFov = this._alpha === 1 ?
+            currentFov :
+            this._interpolateFov(currentFov, this._computePreviousFov(0), this._alpha);
+        var y0 = Math.tan(actualFov / 2 * Math.PI / 180);
+        var y1 = Math.tan(fov / 2 * Math.PI / 180);
+        var zoom = Math.log(y0 / y1) / Math.log(2);
+        return zoom;
+    };
     RenderCamera.prototype.setFrame = function (frame) {
         var state = frame.state;
         if (state.state !== this._state) {
@@ -43273,8 +51906,8 @@ var RenderCamera = /** @class */ (function () {
             this._changed = true;
         }
         if (this._changed) {
-            this._currentFov = this._computeCurrentFov();
-            this._previousFov = this._computePreviousFov();
+            this._currentFov = this._computeCurrentFov(this.zoom);
+            this._previousFov = this._computePreviousFov(this._zoom);
         }
         var alpha = state.alpha;
         if (this._changed || alpha !== this._alpha) {
@@ -43315,59 +51948,40 @@ var RenderCamera = /** @class */ (function () {
     RenderCamera.prototype._computeAspect = function (elementWidth, elementHeight) {
         return elementWidth === 0 ? 0 : elementWidth / elementHeight;
     };
-    RenderCamera.prototype._computeCurrentFov = function () {
+    RenderCamera.prototype._computeCurrentFov = function (zoom) {
+        if (this._perspective.aspect === 0) {
+            return 0;
+        }
         if (!this._currentNodeId) {
             return this._initialFov;
         }
         return this._currentPano ?
-            this._yToFov(1, this._zoom) :
-            this._computeVerticalFov(this._currentProjectedPoints, this._renderMode, this._zoom, this.perspective.aspect);
+            this._yToFov(1, zoom) :
+            this._computeVerticalFov(this._currentProjectedPoints, this._renderMode, zoom, this.perspective.aspect);
     };
     RenderCamera.prototype._computeFov = function () {
-        this._currentFov = this._computeCurrentFov();
-        this._previousFov = this._computePreviousFov();
+        this._currentFov = this._computeCurrentFov(this._zoom);
+        this._previousFov = this._computePreviousFov(this._zoom);
         return this._interpolateFov(this._currentFov, this._previousFov, this._alpha);
     };
-    RenderCamera.prototype._computePreviousFov = function () {
+    RenderCamera.prototype._computePreviousFov = function (zoom) {
+        if (this._perspective.aspect === 0) {
+            return 0;
+        }
         if (!this._currentNodeId) {
             return this._initialFov;
         }
         return !this._previousNodeId ?
             this._currentFov :
             this._previousPano ?
-                this._yToFov(1, this._zoom) :
-                this._computeVerticalFov(this._previousProjectedPoints, this._renderMode, this._zoom, this.perspective.aspect);
+                this._yToFov(1, zoom) :
+                this._computeVerticalFov(this._previousProjectedPoints, this._renderMode, zoom, this.perspective.aspect);
     };
     RenderCamera.prototype._computeProjectedPoints = function (transform) {
-        var _this = this;
-        var os = [[0.5, 0], [1, 0]];
-        var ds = [[0.5, 0], [0, 0.5]];
-        var pointsPerSide = 100;
-        var basicPoints = [];
-        for (var side = 0; side < os.length; ++side) {
-            var o = os[side];
-            var d = ds[side];
-            for (var i = 0; i <= pointsPerSide; ++i) {
-                basicPoints.push([o[0] + d[0] * i / pointsPerSide,
-                    o[1] + d[1] * i / pointsPerSide]);
-            }
-        }
-        var camera = new THREE.Camera();
-        camera.up.copy(transform.upVector());
-        camera.position.copy(new THREE.Vector3().fromArray(transform.unprojectSfM([0, 0], 0)));
-        camera.lookAt(new THREE.Vector3().fromArray(transform.unprojectSfM([0, 0], 10)));
-        camera.updateMatrix();
-        camera.updateMatrixWorld(true);
-        var projectedPoints = basicPoints
-            .map(function (basicPoint) {
-            var worldPoint = transform.unprojectBasic(basicPoint, 10000);
-            var cameraPoint = _this._viewportCoords.worldToCamera(worldPoint, camera);
-            return [
-                Math.abs(cameraPoint[0] / cameraPoint[2]),
-                Math.abs(cameraPoint[1] / cameraPoint[2]),
-            ];
-        });
-        return projectedPoints;
+        var vertices = [[0.5, 0], [1, 0]];
+        var directions = [[0.5, 0], [0, 0.5]];
+        var pointsPerLine = 100;
+        return Geo_1.Geo.computeProjectedPoints(transform, vertices, directions, pointsPerLine, this._viewportCoords);
     };
     RenderCamera.prototype._computeRequiredVerticalFov = function (projectedPoint, zoom, aspect) {
         var maxY = Math.max(projectedPoint[0] / aspect, projectedPoint[1]);
@@ -43376,9 +51990,7 @@ var RenderCamera = /** @class */ (function () {
     RenderCamera.prototype._computeRotation = function (camera) {
         var direction = camera.lookat.clone().sub(camera.position);
         var up = camera.up.clone();
-        var upProjection = direction.clone().dot(up);
-        var planeProjection = direction.clone().sub(up.clone().multiplyScalar(upProjection));
-        var phi = Math.atan2(planeProjection.y, planeProjection.x);
+        var phi = this._spatial.azimuthal(direction.toArray(), up.toArray());
         var theta = Math.PI / 2 - this._spatial.angleToPlane(direction.toArray(), [0, 0, 1]);
         return { phi: phi, theta: theta };
     };
@@ -43410,7 +52022,7 @@ var RenderCamera = /** @class */ (function () {
 exports.RenderCamera = RenderCamera;
 exports.default = RenderCamera;
 
-},{"../Geo":278,"../Render":281,"../State":282,"three":226}],408:[function(require,module,exports){
+},{"../Geo":294,"../Render":297,"../State":298,"three":242}],434:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -43446,7 +52058,7 @@ var RenderMode;
 })(RenderMode = exports.RenderMode || (exports.RenderMode = {}));
 exports.default = RenderMode;
 
-},{}],409:[function(require,module,exports){
+},{}],435:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
@@ -43566,7 +52178,7 @@ exports.RenderService = RenderService;
 exports.default = RenderService;
 
 
-},{"../Geo":278,"../Render":281,"rxjs":27,"rxjs/operators":225}],410:[function(require,module,exports){
+},{"../Geo":294,"../Render":297,"rxjs":43,"rxjs/operators":241}],436:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var FrameGenerator = /** @class */ (function () {
@@ -43615,7 +52227,7 @@ var FrameGenerator = /** @class */ (function () {
 exports.FrameGenerator = FrameGenerator;
 exports.default = FrameGenerator;
 
-},{}],411:[function(require,module,exports){
+},{}],437:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var RotationDelta = /** @class */ (function () {
@@ -43678,7 +52290,7 @@ var RotationDelta = /** @class */ (function () {
 exports.RotationDelta = RotationDelta;
 exports.default = RotationDelta;
 
-},{}],412:[function(require,module,exports){
+},{}],438:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var State;
@@ -43690,7 +52302,7 @@ var State;
 })(State = exports.State || (exports.State = {}));
 exports.default = State;
 
-},{}],413:[function(require,module,exports){
+},{}],439:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var State_1 = require("../State");
@@ -43918,7 +52530,7 @@ var StateContext = /** @class */ (function () {
 }());
 exports.StateContext = StateContext;
 
-},{"../Geo":278,"../State":282}],414:[function(require,module,exports){
+},{"../Geo":294,"../State":298}],440:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -44272,7 +52884,7 @@ var StateService = /** @class */ (function () {
 }());
 exports.StateService = StateService;
 
-},{"../State":282,"rxjs":27,"rxjs/operators":225}],415:[function(require,module,exports){
+},{"../State":298,"rxjs":43,"rxjs/operators":241}],441:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -44303,7 +52915,7 @@ var TransitionMode;
 })(TransitionMode = exports.TransitionMode || (exports.TransitionMode = {}));
 exports.default = TransitionMode;
 
-},{}],416:[function(require,module,exports){
+},{}],442:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -44387,7 +52999,7 @@ exports.EarthState = EarthState;
 exports.default = EarthState;
 
 
-},{"../../State":282,"three":226}],417:[function(require,module,exports){
+},{"../../State":298,"three":242}],443:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -44432,6 +53044,9 @@ var InteractiveStateBase = /** @class */ (function (_super) {
         if (this._currentNode == null) {
             return;
         }
+        if (rotationDelta.phi === 0 && rotationDelta.theta === 0) {
+            return;
+        }
         this._desiredZoom = this._zoom;
         this._desiredLookat = null;
         this._requestedBasicRotation = null;
@@ -44730,7 +53345,8 @@ var InteractiveStateBase = /** @class */ (function (_super) {
         if (this._rotationDelta.isZero) {
             return;
         }
-        this._rotationDelta.multiply(this._rotationAcceleration);
+        var alpha = this.currentNode.fullPano ? 1 : this._alpha;
+        this._rotationDelta.multiply(this._rotationAcceleration * alpha);
         this._rotationDelta.threshold(this._rotationThreshold);
     };
     InteractiveStateBase.prototype._updateRotationBasic = function () {
@@ -44821,7 +53437,7 @@ exports.InteractiveStateBase = InteractiveStateBase;
 exports.default = InteractiveStateBase;
 
 
-},{"../../State":282,"three":226}],418:[function(require,module,exports){
+},{"../../State":298,"three":242}],444:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -44906,7 +53522,7 @@ var InteractiveWaitingState = /** @class */ (function (_super) {
 exports.InteractiveWaitingState = InteractiveWaitingState;
 exports.default = InteractiveWaitingState;
 
-},{"../../State":282}],419:[function(require,module,exports){
+},{"../../State":298}],445:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Error_1 = require("../../Error");
@@ -45246,7 +53862,7 @@ var StateBase = /** @class */ (function () {
 }());
 exports.StateBase = StateBase;
 
-},{"../../Error":277,"../../Geo":278,"../../State":282}],420:[function(require,module,exports){
+},{"../../Error":293,"../../Geo":294,"../../State":298}],446:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -45380,7 +53996,7 @@ var TraversingState = /** @class */ (function (_super) {
 exports.TraversingState = TraversingState;
 exports.default = TraversingState;
 
-},{"../../State":282,"@mapbox/unitbezier":2}],421:[function(require,module,exports){
+},{"../../State":298,"@mapbox/unitbezier":2}],447:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -45454,7 +54070,7 @@ var WaitingState = /** @class */ (function (_super) {
 exports.WaitingState = WaitingState;
 exports.default = WaitingState;
 
-},{"../../State":282}],422:[function(require,module,exports){
+},{"../../State":298}],448:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -45546,7 +54162,7 @@ var ImageTileLoader = /** @class */ (function () {
 exports.ImageTileLoader = ImageTileLoader;
 exports.default = ImageTileLoader;
 
-},{"rxjs":27}],423:[function(require,module,exports){
+},{"rxjs":43}],449:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -45614,7 +54230,7 @@ var ImageTileStore = /** @class */ (function () {
 exports.ImageTileStore = ImageTileStore;
 exports.default = ImageTileStore;
 
-},{}],424:[function(require,module,exports){
+},{}],450:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Geo_1 = require("../Geo");
@@ -45754,7 +54370,7 @@ var RegionOfInterestCalculator = /** @class */ (function () {
 exports.RegionOfInterestCalculator = RegionOfInterestCalculator;
 exports.default = RegionOfInterestCalculator;
 
-},{"../Geo":278}],425:[function(require,module,exports){
+},{"../Geo":294}],451:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
@@ -46230,7 +54846,7 @@ var TextureProvider = /** @class */ (function () {
 exports.TextureProvider = TextureProvider;
 exports.default = TextureProvider;
 
-},{"rxjs":27,"rxjs/operators":225,"three":226}],426:[function(require,module,exports){
+},{"rxjs":43,"rxjs/operators":241,"three":242}],452:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var DOM = /** @class */ (function () {
@@ -46259,7 +54875,7 @@ var DOM = /** @class */ (function () {
 exports.DOM = DOM;
 exports.default = DOM;
 
-},{}],427:[function(require,module,exports){
+},{}],453:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var EventEmitter = /** @class */ (function () {
@@ -46318,7 +54934,7 @@ var EventEmitter = /** @class */ (function () {
 exports.EventEmitter = EventEmitter;
 exports.default = EventEmitter;
 
-},{}],428:[function(require,module,exports){
+},{}],454:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Viewer_1 = require("../Viewer");
@@ -46362,7 +54978,7 @@ var Settings = /** @class */ (function () {
 exports.Settings = Settings;
 exports.default = Settings;
 
-},{"../Viewer":286}],429:[function(require,module,exports){
+},{"../Viewer":302}],455:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 function isBrowser() {
@@ -46432,7 +55048,7 @@ function isWebGLSupported() {
 }
 exports.isWebGLSupported = isWebGLSupported;
 
-},{}],430:[function(require,module,exports){
+},{}],456:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Urls = /** @class */ (function () {
@@ -46466,8 +55082,8 @@ var Urls = /** @class */ (function () {
         enumerable: true,
         configurable: true
     });
-    Urls.atomicReconstruction = function (key) {
-        return Urls._scheme + "://" + Urls._atomicReconstructionHost + "/" + key + "/sfm/v1.0/atomic_reconstruction.json";
+    Urls.clusterReconstruction = function (key) {
+        return Urls._scheme + "://" + Urls._clusterReconstructionHost + "/" + key + "/v1.0/aligned.jsonz";
     };
     Urls.exporeImage = function (key) {
         return Urls._scheme + "://" + Urls._exploreHost + "/app/?pKey=" + key + "&focus=photo";
@@ -46492,8 +55108,8 @@ var Urls = /** @class */ (function () {
         if (!!options.apiHost) {
             Urls._apiHost = options.apiHost;
         }
-        if (!!options.atomicReconstructionHost) {
-            Urls._atomicReconstructionHost = options.atomicReconstructionHost;
+        if (!!options.clusterReconstructionHost) {
+            Urls._clusterReconstructionHost = options.clusterReconstructionHost;
         }
         if (!!options.exploreHost) {
             Urls._exploreHost = options.exploreHost;
@@ -46512,11 +55128,11 @@ var Urls = /** @class */ (function () {
         }
     };
     Urls._apiHost = "a.mapillary.com";
-    Urls._atomicReconstructionHost = "d3necqxnn15whe.cloudfront.net";
+    Urls._clusterReconstructionHost = "cluster-reconstructions.mapillary.com";
     Urls._exploreHost = "www.mapillary.com";
-    Urls._imageHost = "d1cuyjsrcm0gby.cloudfront.net";
-    Urls._imageTileHost = "d2qb1440i7l50o.cloudfront.net";
-    Urls._meshHost = "d1brzeo354iq2l.cloudfront.net";
+    Urls._imageHost = "images.mapillary.com";
+    Urls._imageTileHost = "loris.mapillary.com";
+    Urls._meshHost = "meshes.mapillary.com";
     Urls._origin = "mapillary.webgl";
     Urls._scheme = "https";
     return Urls;
@@ -46524,7 +55140,7 @@ var Urls = /** @class */ (function () {
 exports.Urls = Urls;
 exports.default = Urls;
 
-},{}],431:[function(require,module,exports){
+},{}],457:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -46573,7 +55189,7 @@ var Alignment;
 })(Alignment = exports.Alignment || (exports.Alignment = {}));
 exports.default = Alignment;
 
-},{}],432:[function(require,module,exports){
+},{}],458:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -46657,7 +55273,7 @@ var CacheService = /** @class */ (function () {
 exports.CacheService = CacheService;
 exports.default = CacheService;
 
-},{"../Graph":279,"rxjs":27,"rxjs/operators":225}],433:[function(require,module,exports){
+},{"../Graph":295,"rxjs":43,"rxjs/operators":241}],459:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
@@ -46691,6 +55307,7 @@ var ComponentController = /** @class */ (function () {
                 _this._subscribeCoverComponent();
                 _this._navigator.stateService.start();
                 _this._navigator.cacheService.start();
+                _this._navigator.panService.start();
                 _this._observer.startEmit();
             });
         }
@@ -46777,6 +55394,7 @@ var ComponentController = /** @class */ (function () {
                     .subscribe(function () {
                     _this._navigator.stateService.start();
                     _this._navigator.cacheService.start();
+                    _this._navigator.panService.start();
                     _this._observer.startEmit();
                     _this._coverComponent.configure({ state: Component_1.CoverState.Hidden });
                     _this._componentService.deactivateCover();
@@ -46791,6 +55409,7 @@ var ComponentController = /** @class */ (function () {
                 _this._navigator.stateService.stop();
                 _this._navigator.cacheService.stop();
                 _this._navigator.playService.stop();
+                _this._navigator.panService.stop();
                 _this._componentService.activateCover();
                 _this._setNavigable(conf.key == null);
             }
@@ -46834,7 +55453,7 @@ var ComponentController = /** @class */ (function () {
 }());
 exports.ComponentController = ComponentController;
 
-},{"../Component":275,"rxjs/operators":225}],434:[function(require,module,exports){
+},{"../Component":291,"rxjs/operators":241}],460:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var Render_1 = require("../Render");
@@ -46885,7 +55504,7 @@ var Container = /** @class */ (function () {
 exports.Container = Container;
 exports.default = Container;
 
-},{"../Render":281,"../Utils":285,"../Viewer":286}],435:[function(require,module,exports){
+},{"../Render":297,"../Utils":301,"../Viewer":302}],461:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 /**
@@ -46914,7 +55533,7 @@ var ImageSize;
     ImageSize[ImageSize["Size2048"] = 2048] = "Size2048";
 })(ImageSize = exports.ImageSize || (exports.ImageSize = {}));
 
-},{}],436:[function(require,module,exports){
+},{}],462:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -46942,7 +55561,7 @@ var KeyboardService = /** @class */ (function () {
 exports.KeyboardService = KeyboardService;
 exports.default = KeyboardService;
 
-},{"rxjs":27}],437:[function(require,module,exports){
+},{"rxjs":43}],463:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
@@ -46990,7 +55609,7 @@ var LoadingService = /** @class */ (function () {
 exports.LoadingService = LoadingService;
 exports.default = LoadingService;
 
-},{"rxjs":27,"rxjs/operators":225}],438:[function(require,module,exports){
+},{"rxjs":43,"rxjs/operators":241}],464:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -47371,7 +55990,7 @@ var MouseService = /** @class */ (function () {
 exports.MouseService = MouseService;
 exports.default = MouseService;
 
-},{"rxjs":27,"rxjs/operators":225}],439:[function(require,module,exports){
+},{"rxjs":43,"rxjs/operators":241}],465:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -47382,8 +56001,9 @@ var Edge_1 = require("../Edge");
 var Error_1 = require("../Error");
 var State_1 = require("../State");
 var Viewer_1 = require("../Viewer");
+var PanService_1 = require("./PanService");
 var Navigator = /** @class */ (function () {
-    function Navigator(clientId, options, token, apiV3, graphService, imageLoadingService, loadingService, stateService, cacheService, playService) {
+    function Navigator(clientId, options, token, apiV3, graphService, imageLoadingService, loadingService, stateService, cacheService, playService, panService) {
         this._apiV3 = apiV3 != null ? apiV3 : new API_1.APIv3(clientId, token);
         this._imageLoadingService = imageLoadingService != null ? imageLoadingService : new Graph_1.ImageLoadingService();
         this._graphService = graphService != null ?
@@ -47398,6 +56018,9 @@ var Navigator = /** @class */ (function () {
         this._playService = playService != null ?
             playService :
             new Viewer_1.PlayService(this._graphService, this._stateService);
+        this._panService = panService != null ?
+            panService :
+            new PanService_1.PanService(this._graphService, this._stateService, options.combinedPanning);
         this._keyRequested$ = new rxjs_1.BehaviorSubject(null);
         this._movedToKey$ = new rxjs_1.BehaviorSubject(null);
         this._request$ = null;
@@ -47446,6 +56069,13 @@ var Navigator = /** @class */ (function () {
         enumerable: true,
         configurable: true
     });
+    Object.defineProperty(Navigator.prototype, "panService", {
+        get: function () {
+            return this._panService;
+        },
+        enumerable: true,
+        configurable: true
+    });
     Object.defineProperty(Navigator.prototype, "playService", {
         get: function () {
             return this._playService;
@@ -47611,7 +56241,7 @@ var Navigator = /** @class */ (function () {
 exports.Navigator = Navigator;
 exports.default = Navigator;
 
-},{"../API":274,"../Edge":276,"../Error":277,"../Graph":279,"../State":282,"../Viewer":286,"rxjs":27,"rxjs/operators":225}],440:[function(require,module,exports){
+},{"../API":290,"../Edge":292,"../Error":293,"../Graph":295,"../State":298,"../Viewer":302,"./PanService":467,"rxjs":43,"rxjs/operators":241}],466:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -47650,12 +56280,34 @@ var Observer = /** @class */ (function () {
         enumerable: true,
         configurable: true
     });
+    Object.defineProperty(Observer.prototype, "projection", {
+        get: function () {
+            return this._projection;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Observer.prototype.project$ = function (latLon) {
+        var _this = this;
+        return rxjs_1.combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentNode$, this._navigator.stateService.reference$).pipe(operators_1.first(), operators_1.map(function (_a) {
+            var render = _a[0], node = _a[1], reference = _a[2];
+            if (_this._projection.distanceBetweenLatLons(latLon, node.latLon) > 1000) {
+                return null;
+            }
+            var canvasPoint = _this._projection.latLonToCanvas(latLon, _this._container.element, render, reference);
+            return !!canvasPoint ?
+                [Math.round(canvasPoint[0]), Math.round(canvasPoint[1])] :
+                null;
+        }));
+    };
     Observer.prototype.projectBasic$ = function (basicPoint) {
         var _this = this;
         return rxjs_1.combineLatest(this._container.renderService.renderCamera$, this._navigator.stateService.currentTransform$).pipe(operators_1.first(), operators_1.map(function (_a) {
             var render = _a[0], transform = _a[1];
             var canvasPoint = _this._projection.basicToCanvas(basicPoint, _this._container.element, render, transform);
-            return [Math.round(canvasPoint[0]), Math.round(canvasPoint[1])];
+            return !!canvasPoint ?
+                [Math.round(canvasPoint[0]), Math.round(canvasPoint[1])] :
+                null;
         }));
     };
     Observer.prototype.startEmit = function () {
@@ -47717,6 +56369,45 @@ var Observer = /** @class */ (function () {
             .subscribe(function (event) {
             _this._eventEmitter.fire(event.type, event);
         });
+        this._positionSubscription = this._container.renderService.renderCamera$.pipe(operators_1.distinctUntilChanged(function (_a, _b) {
+            var x1 = _a[0], y1 = _a[1];
+            var x2 = _b[0], y2 = _b[1];
+            return _this._closeTo(x1, x2, 1e-2) &&
+                _this._closeTo(y1, y2, 1e-2);
+        }, function (rc) {
+            return rc.camera.position.toArray();
+        }))
+            .subscribe(function () {
+            _this._eventEmitter.fire(Viewer_1.Viewer.positionchanged, {
+                target: _this._eventEmitter,
+                type: Viewer_1.Viewer.positionchanged,
+            });
+        });
+        this._povSubscription = this._container.renderService.renderCamera$.pipe(operators_1.distinctUntilChanged(function (_a, _b) {
+            var phi1 = _a[0], theta1 = _a[1];
+            var phi2 = _b[0], theta2 = _b[1];
+            return _this._closeTo(phi1, phi2, 1e-3) &&
+                _this._closeTo(theta1, theta2, 1e-3);
+        }, function (rc) {
+            return [rc.rotation.phi, rc.rotation.theta];
+        }))
+            .subscribe(function () {
+            _this._eventEmitter.fire(Viewer_1.Viewer.povchanged, {
+                target: _this._eventEmitter,
+                type: Viewer_1.Viewer.povchanged,
+            });
+        });
+        this._fovSubscription = this._container.renderService.renderCamera$.pipe(operators_1.distinctUntilChanged(function (fov1, fov2) {
+            return _this._closeTo(fov1, fov2, 1e-2);
+        }, function (rc) {
+            return rc.perspective.fov;
+        }))
+            .subscribe(function () {
+            _this._eventEmitter.fire(Viewer_1.Viewer.fovchanged, {
+                target: _this._eventEmitter,
+                type: Viewer_1.Viewer.fovchanged,
+            });
+        });
     };
     Observer.prototype.stopEmit = function () {
         if (!this.started) {
@@ -47725,13 +56416,19 @@ var Observer = /** @class */ (function () {
         this._started = false;
         this._bearingSubscription.unsubscribe();
         this._currentNodeSubscription.unsubscribe();
+        this._fovSubscription.unsubscribe();
         this._moveSubscription.unsubscribe();
+        this._positionSubscription.unsubscribe();
+        this._povSubscription.unsubscribe();
         this._sequenceEdgesSubscription.unsubscribe();
         this._spatialEdgesSubscription.unsubscribe();
         this._viewerMouseEventSubscription.unsubscribe();
         this._bearingSubscription = null;
         this._currentNodeSubscription = null;
+        this._fovSubscription = null;
         this._moveSubscription = null;
+        this._positionSubscription = null;
+        this._povSubscription = null;
         this._sequenceEdgesSubscription = null;
         this._spatialEdgesSubscription = null;
         this._viewerMouseEventSubscription = null;
@@ -47751,6 +56448,9 @@ var Observer = /** @class */ (function () {
             return _this._projection.canvasToBasic(canvasPoint, _this._container.element, render, transform);
         }));
     };
+    Observer.prototype._closeTo = function (v1, v2, absoluteTolerance) {
+        return Math.abs(v1 - v2) <= absoluteTolerance;
+    };
     Observer.prototype._mapMouseEvent$ = function (type, mouseEvent$) {
         return mouseEvent$.pipe(operators_1.map(function (event) {
             return [type, event];
@@ -47761,7 +56461,226 @@ var Observer = /** @class */ (function () {
 exports.Observer = Observer;
 exports.default = Observer;
 
-},{"../Viewer":286,"rxjs":27,"rxjs/operators":225}],441:[function(require,module,exports){
+},{"../Viewer":302,"rxjs":43,"rxjs/operators":241}],467:[function(require,module,exports){
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var rxjs_1 = require("rxjs");
+var operators_1 = require("rxjs/operators");
+var Geo = require("../geo/Geo");
+var GeoCoords_1 = require("../geo/GeoCoords");
+var GraphCalculator_1 = require("../graph/GraphCalculator");
+var Spatial_1 = require("../geo/Spatial");
+var Transform_1 = require("../geo/Transform");
+var ViewportCoords_1 = require("../geo/ViewportCoords");
+var PanMode;
+(function (PanMode) {
+    PanMode[PanMode["Disabled"] = 0] = "Disabled";
+    PanMode[PanMode["Enabled"] = 1] = "Enabled";
+    PanMode[PanMode["Started"] = 2] = "Started";
+})(PanMode || (PanMode = {}));
+var PanService = /** @class */ (function () {
+    function PanService(graphService, stateService, enabled, geoCoords, graphCalculator, spatial, viewportCoords) {
+        this._graphService = graphService;
+        this._stateService = stateService;
+        this._geoCoords = !!geoCoords ? geoCoords : new GeoCoords_1.default();
+        this._graphCalculator = !!graphCalculator ? graphCalculator : new GraphCalculator_1.default(this._geoCoords);
+        this._spatial = !!spatial ? spatial : new Spatial_1.default();
+        this._viewportCoords = !!viewportCoords ? viewportCoords : new ViewportCoords_1.default();
+        this._mode = enabled !== false ? PanMode.Enabled : PanMode.Disabled;
+        this._panNodesSubject$ = new rxjs_1.Subject();
+        this._panNodes$ = this._panNodesSubject$.pipe(operators_1.startWith([]), operators_1.publishReplay(1), operators_1.refCount());
+        this._panNodes$.subscribe();
+    }
+    Object.defineProperty(PanService.prototype, "panNodes$", {
+        get: function () {
+            return this._panNodes$;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    PanService.prototype.enable = function () {
+        if (this._mode !== PanMode.Disabled) {
+            return;
+        }
+        this._mode = PanMode.Enabled;
+        this.start();
+    };
+    PanService.prototype.disable = function () {
+        if (this._mode === PanMode.Disabled) {
+            return;
+        }
+        this.stop();
+        this._mode = PanMode.Disabled;
+    };
+    PanService.prototype.start = function () {
+        var _this = this;
+        if (this._mode !== PanMode.Enabled) {
+            return;
+        }
+        var panNodes$ = this._stateService.currentNode$.pipe(operators_1.switchMap(function (current) {
+            if (!current.merged) {
+                return rxjs_1.of([]);
+            }
+            var current$ = rxjs_1.of(current);
+            var bounds = _this._graphCalculator.boundingBoxCorners(current.latLon, 20);
+            var adjacent$ = _this._graphService
+                .cacheBoundingBox$(bounds[0], bounds[1]).pipe(operators_1.catchError(function (error) {
+                console.error("Failed to cache periphery bounding box (" + current.key + ")", error);
+                return rxjs_1.empty();
+            }), operators_1.map(function (nodes) {
+                if (current.pano) {
+                    return [];
+                }
+                var potential = [];
+                for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
+                    var node = nodes_1[_i];
+                    if (node.key === current.key) {
+                        continue;
+                    }
+                    if (node.mergeCC !== current.mergeCC) {
+                        continue;
+                    }
+                    if (node.pano) {
+                        continue;
+                    }
+                    if (_this._distance(node, current) > 4) {
+                        continue;
+                    }
+                    potential.push(node);
+                }
+                return potential;
+            }));
+            return rxjs_1.combineLatest(current$, adjacent$).pipe(operators_1.withLatestFrom(_this._stateService.reference$), operators_1.map(function (_a) {
+                var _b = _a[0], cn = _b[0], adjacent = _b[1], reference = _a[1];
+                var currentDirection = _this._spatial.viewingDirection(cn.rotation);
+                var currentTranslation = Geo.computeTranslation({ lat: cn.latLon.lat, lon: cn.latLon.lon, alt: cn.alt }, cn.rotation, reference);
+                var currentTransform = _this._createTransform(cn, currentTranslation);
+                var currentAzimuthal = _this._spatial.wrap(_this._spatial.azimuthal(currentDirection.toArray(), currentTransform.upVector().toArray()), 0, 2 * Math.PI);
+                var currentProjectedPoints = _this._computeProjectedPoints(currentTransform);
+                var currentHFov = _this._computeHorizontalFov(currentProjectedPoints) / 180 * Math.PI;
+                var preferredOverlap = Math.PI / 8;
+                var left = undefined;
+                var right = undefined;
+                for (var _i = 0, adjacent_1 = adjacent; _i < adjacent_1.length; _i++) {
+                    var a = adjacent_1[_i];
+                    var translation = Geo.computeTranslation({ lat: a.latLon.lat, lon: a.latLon.lon, alt: a.alt }, a.rotation, reference);
+                    var transform = _this._createTransform(a, translation);
+                    var projectedPoints = _this._computeProjectedPoints(transform);
+                    var hFov = _this._computeHorizontalFov(projectedPoints) / 180 * Math.PI;
+                    var direction = _this._spatial.viewingDirection(a.rotation);
+                    var azimuthal = _this._spatial.wrap(_this._spatial.azimuthal(direction.toArray(), transform.upVector().toArray()), 0, 2 * Math.PI);
+                    var directionChange = _this._spatial.angleBetweenVector2(currentDirection.x, currentDirection.y, direction.x, direction.y);
+                    var overlap = Number.NEGATIVE_INFINITY;
+                    if (directionChange > 0) {
+                        if (currentAzimuthal > azimuthal) {
+                            overlap = currentAzimuthal - 2 * Math.PI + currentHFov / 2 - (azimuthal - hFov / 2);
+                        }
+                        else {
+                            overlap = currentAzimuthal + currentHFov / 2 - (azimuthal - hFov / 2);
+                        }
+                    }
+                    else {
+                        if (currentAzimuthal < azimuthal) {
+                            overlap = azimuthal + hFov / 2 - (currentAzimuthal + 2 * Math.PI - currentHFov / 2);
+                        }
+                        else {
+                            overlap = azimuthal + hFov / 2 - (currentAzimuthal - currentHFov / 2);
+                        }
+                    }
+                    var nonOverlap = Math.abs(hFov - overlap);
+                    var distanceCost = _this._distance(a, cn);
+                    var timeCost = Math.min(_this._timeDifference(a, cn), 4);
+                    var overlapCost = 20 * Math.abs(overlap - preferredOverlap);
+                    var fovCost = Math.min(5, 1 / Math.min(hFov / currentHFov, 1));
+                    var nonOverlapCost = overlap > 0 ? -2 * nonOverlap : 0;
+                    var cost = distanceCost + timeCost + overlapCost + fovCost + nonOverlapCost;
+                    if (overlap > 0 &&
+                        overlap < 0.5 * currentHFov &&
+                        overlap < 0.5 * hFov &&
+                        nonOverlap > 0.5 * currentHFov) {
+                        if (directionChange > 0) {
+                            if (!left) {
+                                left = [cost, a, transform, hFov];
+                            }
+                            else {
+                                if (cost < left[0]) {
+                                    left = [cost, a, transform, hFov];
+                                }
+                            }
+                        }
+                        else {
+                            if (!right) {
+                                right = [cost, a, transform, hFov];
+                            }
+                            else {
+                                if (cost < right[0]) {
+                                    right = [cost, a, transform, hFov];
+                                }
+                            }
+                        }
+                    }
+                }
+                var panNodes = [];
+                if (!!left) {
+                    panNodes.push([left[1], left[2], left[3]]);
+                }
+                if (!!right) {
+                    panNodes.push([right[1], right[2], right[3]]);
+                }
+                return panNodes;
+            }), operators_1.startWith([]));
+        }));
+        this._panNodesSubscription = this._stateService.currentState$.pipe(operators_1.map(function (frame) {
+            return frame.state.nodesAhead > 0;
+        }), operators_1.distinctUntilChanged(), operators_1.switchMap(function (traversing) {
+            return traversing ? rxjs_1.of([]) : panNodes$;
+        }))
+            .subscribe(function (panNodes) {
+            _this._panNodesSubject$.next(panNodes);
+        });
+        this._mode = PanMode.Started;
+    };
+    PanService.prototype.stop = function () {
+        if (this._mode !== PanMode.Started) {
+            return;
+        }
+        this._panNodesSubscription.unsubscribe();
+        this._panNodesSubject$.next([]);
+        this._mode = PanMode.Enabled;
+    };
+    PanService.prototype._distance = function (node, reference) {
+        var _a = this._geoCoords.geodeticToEnu(node.latLon.lat, node.latLon.lon, node.alt, reference.latLon.lat, reference.latLon.lon, reference.alt), x = _a[0], y = _a[1], z = _a[2];
+        return Math.sqrt(x * x + y * y + z * z);
+    };
+    PanService.prototype._timeDifference = function (node, reference) {
+        return Math.abs(node.capturedAt - reference.capturedAt) / (1000 * 60 * 60 * 24 * 30);
+    };
+    PanService.prototype._createTransform = function (node, translation) {
+        return new Transform_1.Transform(node.orientation, node.width, node.height, node.focal, node.scale, node.gpano, node.rotation, translation, node.assetsCached ? node.image : undefined, undefined, node.ck1, node.ck2, node.cameraProjection);
+    };
+    PanService.prototype._computeProjectedPoints = function (transform) {
+        var vertices = [[1, 0]];
+        var directions = [[0, 0.5]];
+        var pointsPerLine = 20;
+        return Geo.computeProjectedPoints(transform, vertices, directions, pointsPerLine, this._viewportCoords);
+    };
+    PanService.prototype._computeHorizontalFov = function (projectedPoints) {
+        var _this = this;
+        var fovs = projectedPoints
+            .map(function (projectedPoint) {
+            return _this._coordToFov(projectedPoint[0]);
+        });
+        var fov = Math.min.apply(Math, fovs);
+        return fov;
+    };
+    PanService.prototype._coordToFov = function (x) {
+        return 2 * Math.atan(x) * 180 / Math.PI;
+    };
+    return PanService;
+}());
+exports.PanService = PanService;
+
+},{"../geo/Geo":409,"../geo/GeoCoords":410,"../geo/Spatial":412,"../geo/Transform":413,"../geo/ViewportCoords":414,"../graph/GraphCalculator":417,"rxjs":43,"rxjs/operators":241}],468:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -48082,19 +57001,21 @@ var PlayService = /** @class */ (function () {
 exports.PlayService = PlayService;
 exports.default = PlayService;
 
-},{"../Edge":276,"../Graph":279,"rxjs":27,"rxjs/operators":225}],442:[function(require,module,exports){
+},{"../Edge":292,"../Graph":295,"rxjs":43,"rxjs/operators":241}],469:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var THREE = require("three");
 var Geo_1 = require("../Geo");
+var Spatial_1 = require("../geo/Spatial");
 var Projection = /** @class */ (function () {
-    function Projection(geoCoords, viewportCoords) {
+    function Projection(geoCoords, viewportCoords, spatial) {
         this._geoCoords = !!geoCoords ? geoCoords : new Geo_1.GeoCoords();
+        this._spatial = !!spatial ? spatial : new Spatial_1.default();
         this._viewportCoords = !!viewportCoords ? viewportCoords : new Geo_1.ViewportCoords();
     }
     Projection.prototype.basicToCanvas = function (basicPoint, container, render, transform) {
         return this._viewportCoords
-            .basicToCanvas(basicPoint[0], basicPoint[1], container, transform, render.perspective);
+            .basicToCanvasSafe(basicPoint[0], basicPoint[1], container, transform, render.perspective);
     };
     Projection.prototype.canvasToBasic = function (canvasPoint, container, render, transform) {
         var basicPoint = this._viewportCoords
@@ -48135,12 +57056,25 @@ var Projection = /** @class */ (function () {
         };
         return unprojection;
     };
+    Projection.prototype.cameraToLatLon = function (render, reference) {
+        var position = render.camera.position;
+        var _a = this._geoCoords.enuToGeodetic(position.x, position.y, position.z, reference.lat, reference.lon, reference.alt), lat = _a[0], lon = _a[1];
+        return { lat: lat, lon: lon };
+    };
+    Projection.prototype.latLonToCanvas = function (latLon, container, render, reference) {
+        var point3d = this._geoCoords.geodeticToEnu(latLon.lat, latLon.lon, 0, reference.lat, reference.lon, reference.alt);
+        var canvas = this._viewportCoords.projectToCanvasSafe(point3d, container, render.perspective);
+        return canvas;
+    };
+    Projection.prototype.distanceBetweenLatLons = function (latLon1, latLon2) {
+        return this._spatial.distanceFromLatLon(latLon1.lat, latLon1.lon, latLon2.lat, latLon2.lon);
+    };
     return Projection;
 }());
 exports.Projection = Projection;
 exports.default = Projection;
 
-},{"../Geo":278,"three":226}],443:[function(require,module,exports){
+},{"../Geo":294,"../geo/Spatial":412,"three":242}],470:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var operators_1 = require("rxjs/operators");
@@ -48333,7 +57267,7 @@ exports.SpriteService = SpriteService;
 exports.default = SpriteService;
 
 
-},{"../Viewer":286,"rxjs":27,"rxjs/operators":225,"three":226,"virtual-dom":231}],444:[function(require,module,exports){
+},{"../Viewer":302,"rxjs":43,"rxjs/operators":241,"three":242,"virtual-dom":247}],471:[function(require,module,exports){
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 var rxjs_1 = require("rxjs");
@@ -48557,7 +57491,7 @@ var TouchService = /** @class */ (function () {
 }());
 exports.TouchService = TouchService;
 
-},{"rxjs":27,"rxjs/operators":225}],445:[function(require,module,exports){
+},{"rxjs":43,"rxjs/operators":241}],472:[function(require,module,exports){
 "use strict";
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = function (d, b) {
@@ -48701,7 +57635,7 @@ var Viewer = /** @class */ (function (_super) {
          * Return a boolean indicating if the viewer is in a navigable state.
          *
          * @description The navigable state indicates if the viewer supports
-         * moving, i.e. calling the {@link moveToKey}, {@link moveDir`}
+         * moving, i.e. calling the {@link moveToKey}, {@link moveDir}
          * and {@link moveCloseTo} methods or changing the authentication state,
          * i.e. calling {@link setAuthToken}. The viewer will not be in a navigable
          * state if the cover is activated and the viewer has been supplied a key.
@@ -48716,6 +57650,14 @@ var Viewer = /** @class */ (function (_super) {
         enumerable: true,
         configurable: true
     });
+    /**
+     * Activate the combined panning functionality.
+     *
+     * @description The combined panning functionality is active by default.
+     */
+    Viewer.prototype.activateCombinedPanning = function () {
+        this._navigator.panService.enable();
+    };
     /**
      * Activate a component.
      *
@@ -48735,6 +57677,15 @@ var Viewer = /** @class */ (function (_super) {
     Viewer.prototype.activateCover = function () {
         this._componentController.activateCover();
     };
+    /**
+     * Deactivate the combined panning functionality.
+     *
+     * @description Deactivating the combined panning functionality
+     * could be needed in scenarios involving sequence only navigation.
+     */
+    Viewer.prototype.deactivateCombinedPanning = function () {
+        this._navigator.panService.disable();
+    };
     /**
      * Deactivate a component.
      *
@@ -48784,6 +57735,17 @@ var Viewer = /** @class */ (function (_super) {
             });
         });
     };
+    /**
+     * Returns the HTML element containing the viewer's <canvas> element.
+     *
+     * @description This is the element to which event bindings for viewer
+     * interactivity (such as panning and zooming) are attached.
+     *
+     * @returns {HTMLElement} The container viewer's <canvas> element.
+     */
+    Viewer.prototype.getCanvasContainer = function () {
+        return this._container.canvasContainer;
+    };
     /**
      * Get the basic coordinates of the current image that is
      * at the center of the viewport.
@@ -48834,6 +57796,80 @@ var Viewer = /** @class */ (function (_super) {
     Viewer.prototype.getContainer = function () {
         return this._container.element;
     };
+    /**
+     * Get the viewer's current vertical field of view.
+     *
+     * @description The vertical field of view rendered on the viewer canvas
+     * measured in degrees.
+     *
+     * @returns {Promise<number>} Promise to the current field of view
+     * of the viewer camera.
+     *
+     * @example
+     * ```
+     * viewer.getFieldOfView().then((fov) => { console.log(fov); });
+     * ```
+     */
+    Viewer.prototype.getFieldOfView = function () {
+        var _this = this;
+        return when.promise(function (resolve, reject) {
+            _this._container.renderService.renderCamera$.pipe(operators_1.first())
+                .subscribe(function (rc) {
+                resolve(rc.perspective.fov);
+            }, function (error) {
+                reject(error);
+            });
+        });
+    };
+    /**
+     * Get the viewer's current point of view.
+     *
+     * @returns {Promise<IPointOfView>} Promise to the current point of view
+     * of the viewer camera.
+     *
+     * @example
+     * ```
+     * viewer.getPointOfView().then((pov) => { console.log(pov); });
+     * ```
+     */
+    Viewer.prototype.getPointOfView = function () {
+        var _this = this;
+        return when.promise(function (resolve, reject) {
+            rxjs_1.combineLatest(_this._container.renderService.renderCamera$, _this._container.renderService.bearing$).pipe(operators_1.first())
+                .subscribe(function (_a) {
+                var rc = _a[0], bearing = _a[1];
+                resolve({
+                    bearing: bearing,
+                    tilt: rc.getTilt(),
+                });
+            }, function (error) {
+                reject(error);
+            });
+        });
+    };
+    /**
+     * Get the viewer's current position
+     *
+     * @returns {Promise<ILatLon>} Promise to the viewers's current
+     * position.
+     *
+     * @example
+     * ```
+     * viewer.getPosition().then((pos) => { console.log(pos); });
+     * ```
+     */
+    Viewer.prototype.getPosition = function () {
+        var _this = this;
+        return when.promise(function (resolve, reject) {
+            rxjs_1.combineLatest(_this._container.renderService.renderCamera$, _this._navigator.stateService.reference$).pipe(operators_1.first())
+                .subscribe(function (_a) {
+                var render = _a[0], reference = _a[1];
+                resolve(_this._observer.projection.cameraToLatLon(render, reference));
+            }, function (error) {
+                reject(error);
+            });
+        });
+    };
     /**
      * Get the image's current zoom level.
      *
@@ -48869,7 +57905,7 @@ var Viewer = /** @class */ (function (_super) {
      * longitude.
      * @throws {Error} Propagates any IO errors to the caller.
      * @throws {Error} When viewer is not navigable.
-     * @throws {AbortMapillaryError} When a subsequent move request is made
+     * @throws  {@link AbortMapillaryError} When a subsequent move request is made
      * before the move close to call has completed.
      *
      * @example
@@ -48902,7 +57938,7 @@ var Viewer = /** @class */ (function (_super) {
      * or the edges has not yet been cached.
      * @throws {Error} Propagates any IO errors to the caller.
      * @throws {Error} When viewer is not navigable.
-     * @throws {AbortMapillaryError} When a subsequent move request is made
+     * @throws  {@link AbortMapillaryError} When a subsequent move request is made
      * before the move dir call has completed.
      *
      * @example
@@ -48931,7 +57967,7 @@ var Viewer = /** @class */ (function (_super) {
      * @returns {Promise<Node>} Promise to the node that was navigated to.
      * @throws {Error} Propagates any IO errors to the caller.
      * @throws {Error} When viewer is not navigable.
-     * @throws {AbortMapillaryError} When a subsequent move request is made
+     * @throws  {@link AbortMapillaryError} When a subsequent move request is made
      * before the move to key call has completed.
      *
      * @example
@@ -48953,12 +57989,60 @@ var Viewer = /** @class */ (function (_super) {
             });
         });
     };
+    /**
+     * Project an ILatLon representing geographicalcoordinates to
+     * canvas pixel coordinates.
+     *
+     * @description The geographical coordinates may not always correspond to pixel
+     * coordinates, e.g. if the geographical coordinates have a position behind the
+     * viewer camera. In the case of no correspondence the returned value will
+     * be `null`.
+     *
+     * If the distance from the viewer camera position to the provided lat-lon
+     * is more than 1000 meters `null` will be returned.
+     *
+     * The projection is performed from the ground plane, i.e.
+     * the altitude with respect to the ground plane for the geographical
+     * point is zero.
+     *
+     * Note that whenever the camera moves, the result of the method will be
+     * different.
+     *
+     * @param {ILatLon} latLon - Geographical coordinates to project.
+     * @returns {Promise<Array<number>>} Promise to the pixel coordinates corresponding
+     * to the latLon.
+     *
+     * @example
+     * ```
+     * viewer.project({ lat: 0, lon: 0 })
+     *     .then((pixelPoint) => {
+     *          if (!pixelPoint) {
+     *              console.log("no correspondence");
+     *          }
+     *
+     *          console.log(pixelPoint);
+     *     });
+     * ```
+     */
+    Viewer.prototype.project = function (latLon) {
+        var _this = this;
+        return when.promise(function (resolve, reject) {
+            _this._observer.project$(latLon)
+                .subscribe(function (pixelPoint) {
+                resolve(pixelPoint);
+            }, function (error) {
+                reject(error);
+            });
+        });
+    };
     /**
      * Project basic image coordinates for the current node to canvas pixel
      * coordinates.
      *
      * @description The basic image coordinates may not always correspond to a
-     * pixel point that lies in the visible area of the viewer container.
+     * pixel point that lies in the visible area of the viewer container. In the
+     * case of no correspondence the returned value can be `null`.
+     *
      *
      * @param {Array<number>} basicPoint - Basic images coordinates to project.
      * @returns {Promise<Array<number>>} Promise to the pixel coordinates corresponding
@@ -49092,12 +58176,30 @@ var Viewer = /** @class */ (function (_super) {
      *
      * Clear the filter by setting it to null or empty array.
      *
+     * Commonly used filter properties (see the {@link Node} class
+     * documentation for a full list of properties that can be used
+     * in a filter) and common use cases:
+     *
+     * ```
+     * fullPano        // Show only full 360 panoramas or not
+     * organizationKey // Show images from one or several organizations
+     * sequenceKey     // Show images from one or several sequences
+     * userKey         // Show images from one or several users
+     * capturedAt      // Show images from a certain time interval
+     * ```
+     *
      * @param {FilterExpression} filter - The filter expression.
      * @returns {Promise<void>} Promise that resolves after filter is applied.
      *
      * @example
      * ```
      * viewer.setFilter(["==", "sequenceKey", "<my sequence key>"]);
+     *
+     * // Other examples
+     * // viewer.setFilter(["==", "organizationKey", "<my organization key>"]);
+     * // viewer.setFilter(["in", "userKey", "<my user key #1>", "<my user key #2>"]);
+     * // viewer.setFilter(["==", "fullPano", true]);
+     * // viewer.setFilter([">=", "capturedAt", <my time stamp>]);
      * ```
      */
     Viewer.prototype.setFilter = function (filter) {
@@ -49111,6 +58213,30 @@ var Viewer = /** @class */ (function (_super) {
             });
         });
     };
+    /**
+     * Set the viewer's current vertical field of view.
+     *
+     * @description Sets the vertical field of view rendered
+     * on the viewer canvas measured in degrees. The value
+     * will be clamped to be able to set a valid zoom level
+     * based on the projection model of the current image and
+     * the viewer's current render mode.
+     *
+     * @param {number} fov - Vertical field of view in degrees.
+     *
+     * @example
+     * ```
+     * viewer.setFieldOfView(45);
+     * ```
+     */
+    Viewer.prototype.setFieldOfView = function (fov) {
+        var _this = this;
+        this._container.renderService.renderCamera$.pipe(operators_1.first())
+            .subscribe(function (rc) {
+            var zoom = rc.fovToZoom(fov);
+            _this._navigator.stateService.setZoom(zoom);
+        });
+    };
     /**
      * Set the viewer's render mode.
      *
@@ -49162,6 +58288,9 @@ var Viewer = /** @class */ (function (_super) {
      * coordinates. In the case of no correspondence the returned value will
      * be `null`.
      *
+     * The unprojection to a latLon will be performed towards the ground plane, i.e.
+     * the altitude with respect to the ground plane for the returned latLon is zero.
+     *
      * @param {Array<number>} pixelPoint - Pixel coordinates to unproject.
      * @returns {Promise<ILatLon>} Promise to the latLon corresponding to the pixel point.
      *
@@ -49215,7 +58344,7 @@ var Viewer = /** @class */ (function (_super) {
      * Fired when the viewing direction of the camera changes.
      *
      * @description Related to the computed compass angle
-     * ({@link Node.computedCa}) from SfM, not the original EXIF compass
+     * ({@link Node.computedCA}) from SfM, not the original EXIF compass
      * angle.
      *
      * @event
@@ -49227,22 +58356,29 @@ var Viewer = /** @class */ (function (_super) {
      * Fired when a pointing device (usually a mouse) is pressed and released at
      * the same point in the viewer.
      * @event
-     * @type {IViewerMouseEvent} event - Viewer mouse event data.
+     * @type  {@link IViewerMouseEvent} event - Viewer mouse event data.
      */
     Viewer.click = "click";
     /**
      * Fired when the right button of the mouse is clicked within the viewer.
      * @event
-     * @type {IViewerMouseEvent} event - Viewer mouse event data.
+     * @type  {@link IViewerMouseEvent} event - Viewer mouse event data.
      */
     Viewer.contextmenu = "contextmenu";
     /**
      * Fired when a pointing device (usually a mouse) is clicked twice at
      * the same point in the viewer.
      * @event
-     * @type {IViewerMouseEvent} event - Viewer mouse event data.
+     * @type  {@link IViewerMouseEvent} event - Viewer mouse event data.
      */
     Viewer.dblclick = "dblclick";
+    /**
+     * Fired when the viewer's vertical field of view changes.
+     *
+     * @event
+     * @type  {@link IViewerEvent} event - The event object.
+     */
+    Viewer.fovchanged = "fovchanged";
     /**
      * Fired when the viewer is loading more data.
      * @event
@@ -49252,32 +58388,32 @@ var Viewer = /** @class */ (function (_super) {
     /**
      * Fired when a pointing device (usually a mouse) is pressed within the viewer.
      * @event
-     * @type {IViewerMouseEvent} event - Viewer mouse event data.
+     * @type  {@link IViewerMouseEvent} event - Viewer mouse event data.
      */
     Viewer.mousedown = "mousedown";
     /**
      * Fired when a pointing device (usually a mouse) is moved within the viewer.
      * @description Will not fire when the mouse is actively used, e.g. for drag pan.
      * @event
-     * @type {IViewerMouseEvent} event - Viewer mouse event data.
+     * @type  {@link IViewerMouseEvent} event - Viewer mouse event data.
      */
     Viewer.mousemove = "mousemove";
     /**
      * Fired when a pointing device (usually a mouse) leaves the viewer's canvas.
      * @event
-     * @type {IViewerMouseEvent} event - Viewer mouse event data.
+     * @type  {@link IViewerMouseEvent} event - Viewer mouse event data.
      */
     Viewer.mouseout = "mouseout";
     /**
      * Fired when a pointing device (usually a mouse) is moved onto the viewer's canvas.
      * @event
-     * @type {IViewerMouseEvent} event - Viewer mouse event data.
+     * @type  {@link IViewerMouseEvent} event - Viewer mouse event data.
      */
     Viewer.mouseover = "mouseover";
     /**
      * Fired when a pointing device (usually a mouse) is released within the viewer.
      * @event
-     * @type {IViewerMouseEvent} event - Viewer mouse event data.
+     * @type  {@link IViewerMouseEvent} event - Viewer mouse event data.
      */
     Viewer.mouseup = "mouseup";
     /**
@@ -49309,26 +58445,45 @@ var Viewer = /** @class */ (function (_super) {
     Viewer.navigablechanged = "navigablechanged";
     /**
      * Fired every time the viewer navigates to a new node.
+     *
      * @event
-     * @type {Node} node - Current node.
+     * @type  {@link Node} node - Current node.
      */
     Viewer.nodechanged = "nodechanged";
+    /**
+     * Fired when the viewer's position changes.
+     *
+     * @description The viewer's position changes when transitioning
+     * between nodes.
+     *
+     * @event
+     * @type  {@link IViewerEvent} event - The event object.
+     */
+    Viewer.positionchanged = "positionchanged";
+    /**
+     * Fired when the viewer's point of view changes. The point of view changes
+     * when the bearing, or tilt changes.
+     *
+     * @event
+     * @type  {@link IViewerEvent} event - The event object.
+     */
+    Viewer.povchanged = "povchanged";
     /**
      * Fired every time the sequence edges of the current node changes.
      * @event
-     * @type {IEdgeStatus} status - The edge status object.
+     * @type  {@link IEdgeStatus} status - The edge status object.
      */
     Viewer.sequenceedgeschanged = "sequenceedgeschanged";
     /**
      * Fired every time the spatial edges of the current node changes.
      * @event
-     * @type {IEdgeStatus} status - The edge status object.
+     * @type  {@link IEdgeStatus} status - The edge status object.
      */
     Viewer.spatialedgeschanged = "spatialedgeschanged";
     return Viewer;
 }(Utils_1.EventEmitter));
 exports.Viewer = Viewer;
 
-},{"../Utils":285,"../Viewer":286,"rxjs":27,"rxjs/operators":225,"when":272}]},{},[280])(280)
+},{"../Utils":301,"../Viewer":302,"rxjs":43,"rxjs/operators":241,"when":288}]},{},[296])(296)
 });
 //# sourceMappingURL=mapillary.js.map